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