1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -instsimplify -S < %s | FileCheck %s 3 4; All these are negative cases, we are not allowed to perform this 5; simplification in InstSimplify, because the PHI's aren't def-reachable 6; from one another. 7 8; Most basic case, fully identical PHI nodes 9define void @test0(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) { 10; CHECK-LABEL: @test0( 11; CHECK-NEXT: entry: 12; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]] 13; CHECK: b0: 14; CHECK-NEXT: br label [[END:%.*]] 15; CHECK: b1: 16; CHECK-NEXT: br label [[END]] 17; CHECK: end: 18; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ] 19; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ] 20; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4 21; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4 22; CHECK-NEXT: ret void 23; 24entry: 25 br i1 %c, label %b0, label %b1 26 27b0: 28 br label %end 29 30b1: 31 br label %end 32 33end: 34 %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 35 %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 36 store i32 %i0, i32* %d0 37 store i32 %i1, i32* %d1 38 ret void 39} 40 41; Fully identical PHI nodes, but order of operands differs 42define void @test1(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) { 43; CHECK-LABEL: @test1( 44; CHECK-NEXT: entry: 45; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]] 46; CHECK: b0: 47; CHECK-NEXT: br label [[END:%.*]] 48; CHECK: b1: 49; CHECK-NEXT: br label [[END]] 50; CHECK: end: 51; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ] 52; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V1]], [[B1]] ], [ [[V0]], [[B0]] ] 53; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4 54; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4 55; CHECK-NEXT: ret void 56; 57entry: 58 br i1 %c, label %b0, label %b1 59 60b0: 61 br label %end 62 63b1: 64 br label %end 65 66end: 67 %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 68 %i1 = phi i32 [ %v1, %b1 ], [ %v0, %b0 ] 69 store i32 %i0, i32* %d0 70 store i32 %i1, i32* %d1 71 ret void 72} 73 74; Different incoming values in second PHI 75define void @negative_test2(i32 %v0, i32 %v1, i32 %v2, i1 %c, i32* %d0, i32* %d1) { 76; CHECK-LABEL: @negative_test2( 77; CHECK-NEXT: entry: 78; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]] 79; CHECK: b0: 80; CHECK-NEXT: br label [[END:%.*]] 81; CHECK: b1: 82; CHECK-NEXT: br label [[END]] 83; CHECK: end: 84; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ] 85; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V2:%.*]], [[B1]] ] 86; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4 87; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4 88; CHECK-NEXT: ret void 89; 90entry: 91 br i1 %c, label %b0, label %b1 92 93b0: 94 br label %end 95 96b1: 97 br label %end 98 99end: 100 %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 101 %i1 = phi i32 [ %v0, %b0 ], [ %v2, %b1 ] ; from %b0 takes %v2 instead of %v1 102 store i32 %i0, i32* %d0 103 store i32 %i1, i32* %d1 104 ret void 105} 106define void @negative_test3(i32 %v0, i32 %v1, i32 %v2, i1 %c, i32* %d0, i32* %d1) { 107; CHECK-LABEL: @negative_test3( 108; CHECK-NEXT: entry: 109; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]] 110; CHECK: b0: 111; CHECK-NEXT: br label [[END:%.*]] 112; CHECK: b1: 113; CHECK-NEXT: br label [[END]] 114; CHECK: end: 115; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ] 116; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V2:%.*]], [[B1]] ], [ [[V0]], [[B0]] ] 117; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4 118; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4 119; CHECK-NEXT: ret void 120; 121entry: 122 br i1 %c, label %b0, label %b1 123 124b0: 125 br label %end 126 127b1: 128 br label %end 129 130end: 131 %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 132 %i1 = phi i32 [ %v2, %b1 ], [ %v0, %b0 ] ; from %b0 takes %v2 instead of %v1 133 store i32 %i0, i32* %d0 134 store i32 %i1, i32* %d1 135 ret void 136} 137define void @negative_test4(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) { 138; CHECK-LABEL: @negative_test4( 139; CHECK-NEXT: entry: 140; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]] 141; CHECK: b0: 142; CHECK-NEXT: br label [[END:%.*]] 143; CHECK: b1: 144; CHECK-NEXT: br label [[END]] 145; CHECK: end: 146; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ] 147; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V1]], [[B1]] ], [ [[V0]], [[B0]] ] 148; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4 149; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4 150; CHECK-NEXT: ret void 151; 152entry: 153 br i1 %c, label %b0, label %b1 154 155b0: 156 br label %end 157 158b1: 159 br label %end 160 161end: 162 %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 163 %i1 = phi i32 [ %v1, %b1 ], [ %v0, %b0 ] ; incoming values are swapped 164 store i32 %i0, i32* %d0 165 store i32 %i1, i32* %d1 166 ret void 167} 168 169; Both PHI's are identical, but the first one has no uses, so ignore it. 170define void @test5(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) { 171; CHECK-LABEL: @test5( 172; CHECK-NEXT: entry: 173; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]] 174; CHECK: b0: 175; CHECK-NEXT: br label [[END:%.*]] 176; CHECK: b1: 177; CHECK-NEXT: br label [[END]] 178; CHECK: end: 179; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ] 180; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4 181; CHECK-NEXT: ret void 182; 183entry: 184 br i1 %c, label %b0, label %b1 185 186b0: 187 br label %end 188 189b1: 190 br label %end 191 192end: 193 %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] ; unused 194 %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 195 store i32 %i1, i32* %d1 196 ret void 197} 198; Second PHI has no uses 199define void @test6(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) { 200; CHECK-LABEL: @test6( 201; CHECK-NEXT: entry: 202; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]] 203; CHECK: b0: 204; CHECK-NEXT: br label [[END:%.*]] 205; CHECK: b1: 206; CHECK-NEXT: br label [[END]] 207; CHECK: end: 208; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ] 209; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4 210; CHECK-NEXT: ret void 211; 212entry: 213 br i1 %c, label %b0, label %b1 214 215b0: 216 br label %end 217 218b1: 219 br label %end 220 221end: 222 %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 223 %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] ; unused 224 store i32 %i0, i32* %d0 225 ret void 226} 227 228; Non-matching PHI node should be ignored without terminating CSE. 229define void @test7(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1, i16* %d2) { 230; CHECK-LABEL: @test7( 231; CHECK-NEXT: entry: 232; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]] 233; CHECK: b0: 234; CHECK-NEXT: br label [[END:%.*]] 235; CHECK: b1: 236; CHECK-NEXT: br label [[END]] 237; CHECK: end: 238; CHECK-NEXT: [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ] 239; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ] 240; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ] 241; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4 242; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4 243; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2 244; CHECK-NEXT: ret void 245; 246entry: 247 br i1 %c, label %b0, label %b1 248 249b0: 250 br label %end 251 252b1: 253 br label %end 254 255end: 256 %iBAD = phi i16 [ %v2, %b0 ], [ %v3, %b1 ] 257 %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 258 %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 259 store i32 %i0, i32* %d0 260 store i32 %i1, i32* %d1 261 store i16 %iBAD, i16* %d2 262 ret void 263} 264define void @test8(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1, i16* %d2) { 265; CHECK-LABEL: @test8( 266; CHECK-NEXT: entry: 267; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]] 268; CHECK: b0: 269; CHECK-NEXT: br label [[END:%.*]] 270; CHECK: b1: 271; CHECK-NEXT: br label [[END]] 272; CHECK: end: 273; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ] 274; CHECK-NEXT: [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ] 275; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ] 276; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4 277; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4 278; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2 279; CHECK-NEXT: ret void 280; 281entry: 282 br i1 %c, label %b0, label %b1 283 284b0: 285 br label %end 286 287b1: 288 br label %end 289 290end: 291 %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 292 %iBAD = phi i16 [ %v2, %b0 ], [ %v3, %b1 ] 293 %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 294 store i32 %i0, i32* %d0 295 store i32 %i1, i32* %d1 296 store i16 %iBAD, i16* %d2 297 ret void 298} 299define void @test9(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1, i16* %d2) { 300; CHECK-LABEL: @test9( 301; CHECK-NEXT: entry: 302; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]] 303; CHECK: b0: 304; CHECK-NEXT: br label [[END:%.*]] 305; CHECK: b1: 306; CHECK-NEXT: br label [[END]] 307; CHECK: end: 308; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ] 309; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ] 310; CHECK-NEXT: [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ] 311; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4 312; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4 313; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2 314; CHECK-NEXT: ret void 315; 316entry: 317 br i1 %c, label %b0, label %b1 318 319b0: 320 br label %end 321 322b1: 323 br label %end 324 325end: 326 %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 327 %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] 328 %iBAD = phi i16 [ %v2, %b0 ], [ %v3, %b1 ] 329 store i32 %i0, i32* %d0 330 store i32 %i1, i32* %d1 331 store i16 %iBAD, i16* %d2 332 ret void 333} 334