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