1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -instcombine < %s | FileCheck %s 3 4declare void @usei32(i32) 5 6; If we have a phi of extractvalues, we can sink it, 7; Here, we only need a PHI for extracted values. 8define i32 @test0({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) { 9; CHECK-LABEL: @test0( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 12; CHECK: left: 13; CHECK-NEXT: br label [[END:%.*]] 14; CHECK: right: 15; CHECK-NEXT: br label [[END]] 16; CHECK: end: 17; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ] 18; CHECK-NEXT: [[R:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN]], 0 19; CHECK-NEXT: ret i32 [[R]] 20; 21entry: 22 br i1 %c, label %left, label %right 23 24left: 25 %i0 = extractvalue { i32, i32 } %agg_left, 0 26 br label %end 27 28right: 29 %i1 = extractvalue { i32, i32 } %agg_right, 0 30 br label %end 31 32end: 33 %r = phi i32 [ %i0, %left ], [ %i1, %right ] 34 ret i32 %r 35} 36 37; But only if the extractvalues have no extra uses 38define i32 @test1_extrause0({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) { 39; CHECK-LABEL: @test1_extrause0( 40; CHECK-NEXT: entry: 41; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 42; CHECK: left: 43; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0 44; CHECK-NEXT: call void @usei32(i32 [[I0]]) 45; CHECK-NEXT: br label [[END:%.*]] 46; CHECK: right: 47; CHECK-NEXT: [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 0 48; CHECK-NEXT: br label [[END]] 49; CHECK: end: 50; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ] 51; CHECK-NEXT: ret i32 [[R]] 52; 53entry: 54 br i1 %c, label %left, label %right 55 56left: 57 %i0 = extractvalue { i32, i32 } %agg_left, 0 58 call void @usei32(i32 %i0) 59 br label %end 60 61right: 62 %i1 = extractvalue { i32, i32 } %agg_right, 0 63 br label %end 64 65end: 66 %r = phi i32 [ %i0, %left ], [ %i1, %right ] 67 ret i32 %r 68} 69define i32 @test2_extrause1({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) { 70; CHECK-LABEL: @test2_extrause1( 71; CHECK-NEXT: entry: 72; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 73; CHECK: left: 74; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0 75; CHECK-NEXT: br label [[END:%.*]] 76; CHECK: right: 77; CHECK-NEXT: [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 0 78; CHECK-NEXT: call void @usei32(i32 [[I1]]) 79; CHECK-NEXT: br label [[END]] 80; CHECK: end: 81; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ] 82; CHECK-NEXT: ret i32 [[R]] 83; 84entry: 85 br i1 %c, label %left, label %right 86 87left: 88 %i0 = extractvalue { i32, i32 } %agg_left, 0 89 br label %end 90 91right: 92 %i1 = extractvalue { i32, i32 } %agg_right, 0 93 call void @usei32(i32 %i1) 94 br label %end 95 96end: 97 %r = phi i32 [ %i0, %left ], [ %i1, %right ] 98 ret i32 %r 99} 100define i32 @test3_extrause2({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) { 101; CHECK-LABEL: @test3_extrause2( 102; CHECK-NEXT: entry: 103; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 104; CHECK: left: 105; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0 106; CHECK-NEXT: call void @usei32(i32 [[I0]]) 107; CHECK-NEXT: br label [[END:%.*]] 108; CHECK: right: 109; CHECK-NEXT: [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 0 110; CHECK-NEXT: call void @usei32(i32 [[I1]]) 111; CHECK-NEXT: br label [[END]] 112; CHECK: end: 113; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ] 114; CHECK-NEXT: ret i32 [[R]] 115; 116entry: 117 br i1 %c, label %left, label %right 118 119left: 120 %i0 = extractvalue { i32, i32 } %agg_left, 0 121 call void @usei32(i32 %i0) 122 br label %end 123 124right: 125 %i1 = extractvalue { i32, i32 } %agg_right, 0 126 call void @usei32(i32 %i1) 127 br label %end 128 129end: 130 %r = phi i32 [ %i0, %left ], [ %i1, %right ] 131 ret i32 %r 132} 133 134; But the indicies must match 135define i32 @test4({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) { 136; CHECK-LABEL: @test4( 137; CHECK-NEXT: entry: 138; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 139; CHECK: left: 140; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0 141; CHECK-NEXT: br label [[END:%.*]] 142; CHECK: right: 143; CHECK-NEXT: [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 1 144; CHECK-NEXT: br label [[END]] 145; CHECK: end: 146; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ] 147; CHECK-NEXT: ret i32 [[R]] 148; 149entry: 150 br i1 %c, label %left, label %right 151 152left: 153 %i0 = extractvalue { i32, i32 } %agg_left, 0 154 br label %end 155 156right: 157 %i1 = extractvalue { i32, i32 } %agg_right, 1 158 br label %end 159 160end: 161 %r = phi i32 [ %i0, %left ], [ %i1, %right ] 162 ret i32 %r 163} 164 165; More complex aggregates are fine, too, as long as indicies match. 166define i32 @test5({{ i32, i32 }, { i32, i32 }} %agg_left, {{ i32, i32 }, { i32, i32 }} %agg_right, i1 %c) { 167; CHECK-LABEL: @test5( 168; CHECK-NEXT: entry: 169; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 170; CHECK: left: 171; CHECK-NEXT: br label [[END:%.*]] 172; CHECK: right: 173; CHECK-NEXT: br label [[END]] 174; CHECK: end: 175; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { { i32, i32 }, { i32, i32 } } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ] 176; CHECK-NEXT: [[R:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_LEFT_PN]], 0, 0 177; CHECK-NEXT: ret i32 [[R]] 178; 179entry: 180 br i1 %c, label %left, label %right 181 182left: 183 %i0 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_left, 0, 0 184 br label %end 185 186right: 187 %i1 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_right, 0, 0 188 br label %end 189 190end: 191 %r = phi i32 [ %i0, %left ], [ %i1, %right ] 192 ret i32 %r 193} 194 195; The indicies must fully match, on all levels. 196define i32 @test6({{ i32, i32 }, { i32, i32 }} %agg_left, {{ i32, i32 }, { i32, i32 }} %agg_right, i1 %c) { 197; CHECK-LABEL: @test6( 198; CHECK-NEXT: entry: 199; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 200; CHECK: left: 201; CHECK-NEXT: [[I0:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_LEFT:%.*]], 0, 0 202; CHECK-NEXT: br label [[END:%.*]] 203; CHECK: right: 204; CHECK-NEXT: [[I1:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_RIGHT:%.*]], 0, 1 205; CHECK-NEXT: br label [[END]] 206; CHECK: end: 207; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ] 208; CHECK-NEXT: ret i32 [[R]] 209; 210entry: 211 br i1 %c, label %left, label %right 212 213left: 214 %i0 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_left, 0, 0 215 br label %end 216 217right: 218 %i1 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_right, 0, 1 219 br label %end 220 221end: 222 %r = phi i32 [ %i0, %left ], [ %i1, %right ] 223 ret i32 %r 224} 225define i32 @test7({{ i32, i32 }, { i32, i32 }} %agg_left, {{ i32, i32 }, { i32, i32 }} %agg_right, i1 %c) { 226; CHECK-LABEL: @test7( 227; CHECK-NEXT: entry: 228; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 229; CHECK: left: 230; CHECK-NEXT: [[I0:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_LEFT:%.*]], 0, 0 231; CHECK-NEXT: br label [[END:%.*]] 232; CHECK: right: 233; CHECK-NEXT: [[I1:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_RIGHT:%.*]], 1, 0 234; CHECK-NEXT: br label [[END]] 235; CHECK: end: 236; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ] 237; CHECK-NEXT: ret i32 [[R]] 238; 239entry: 240 br i1 %c, label %left, label %right 241 242left: 243 %i0 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_left, 0, 0 244 br label %end 245 246right: 247 %i1 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_right, 1, 0 248 br label %end 249 250end: 251 %r = phi i32 [ %i0, %left ], [ %i1, %right ] 252 ret i32 %r 253} 254define i32 @test8({{ i32, i32 }, { i32, i32 }} %agg_left, {{ i32, i32 }, { i32, i32 }} %agg_right, i1 %c) { 255; CHECK-LABEL: @test8( 256; CHECK-NEXT: entry: 257; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 258; CHECK: left: 259; CHECK-NEXT: [[I0:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_LEFT:%.*]], 0, 0 260; CHECK-NEXT: br label [[END:%.*]] 261; CHECK: right: 262; CHECK-NEXT: [[I1:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_RIGHT:%.*]], 1, 1 263; CHECK-NEXT: br label [[END]] 264; CHECK: end: 265; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ] 266; CHECK-NEXT: ret i32 [[R]] 267; 268entry: 269 br i1 %c, label %left, label %right 270 271left: 272 %i0 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_left, 0, 0 273 br label %end 274 275right: 276 %i1 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_right, 1, 1 277 br label %end 278 279end: 280 %r = phi i32 [ %i0, %left ], [ %i1, %right ] 281 ret i32 %r 282} 283 284; Also, unlike PHI-of-insertvalues, here the base aggregates of extractvalue 285; can have different types, and just checking the indicies is not enough. 286define i32 @test9({ i32, i32 } %agg_left, { i32, { i32, i32 } } %agg_right, i1 %c) { 287; CHECK-LABEL: @test9( 288; CHECK-NEXT: entry: 289; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 290; CHECK: left: 291; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0 292; CHECK-NEXT: br label [[END:%.*]] 293; CHECK: right: 294; CHECK-NEXT: [[I1:%.*]] = extractvalue { i32, { i32, i32 } } [[AGG_RIGHT:%.*]], 0 295; CHECK-NEXT: br label [[END]] 296; CHECK: end: 297; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ] 298; CHECK-NEXT: ret i32 [[R]] 299; 300entry: 301 br i1 %c, label %left, label %right 302 303left: 304 %i0 = extractvalue { i32, i32 } %agg_left, 0 305 br label %end 306 307right: 308 %i1 = extractvalue { i32, { i32, i32 } } %agg_right, 0 309 br label %end 310 311end: 312 %r = phi i32 [ %i0, %left ], [ %i1, %right ] 313 ret i32 %r 314} 315 316; It is fine if there are multiple uses of the PHI's value, as long as they are all in the PHI node itself 317define i32 @test10({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c0, i1 %c1) { 318; CHECK-LABEL: @test10( 319; CHECK-NEXT: entry: 320; CHECK-NEXT: br i1 [[C0:%.*]], label [[END:%.*]], label [[DISPATCH:%.*]] 321; CHECK: dispatch: 322; CHECK-NEXT: br i1 [[C1:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 323; CHECK: left: 324; CHECK-NEXT: br label [[END]] 325; CHECK: right: 326; CHECK-NEXT: br label [[END]] 327; CHECK: end: 328; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[ENTRY:%.*]] ], [ [[AGG_LEFT]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ] 329; CHECK-NEXT: [[R:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN]], 0 330; CHECK-NEXT: ret i32 [[R]] 331; 332entry: 333 %i0 = extractvalue { i32, i32 } %agg_left, 0 334 %i1 = extractvalue { i32, i32 } %agg_right, 0 335 br i1 %c0, label %end, label %dispatch 336 337dispatch: 338 br i1 %c1, label %left, label %right 339 340left: 341 br label %end 342 343right: 344 br label %end 345 346end: 347 %r = phi i32 [ %i0, %entry ], [ %i0, %left ], [ %i1, %right ] 348 ret i32 %r 349} 350; Which isn't the case here, there is a legitimate external use. 351define i32 @test11({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c0, i1 %c1) { 352; CHECK-LABEL: @test11( 353; CHECK-NEXT: entry: 354; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0 355; CHECK-NEXT: [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 0 356; CHECK-NEXT: call void @usei32(i32 [[I0]]) 357; CHECK-NEXT: br i1 [[C0:%.*]], label [[END:%.*]], label [[DISPATCH:%.*]] 358; CHECK: dispatch: 359; CHECK-NEXT: br i1 [[C1:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 360; CHECK: left: 361; CHECK-NEXT: br label [[END]] 362; CHECK: right: 363; CHECK-NEXT: br label [[END]] 364; CHECK: end: 365; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[I0]], [[ENTRY:%.*]] ], [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ] 366; CHECK-NEXT: ret i32 [[R]] 367; 368entry: 369 %i0 = extractvalue { i32, i32 } %agg_left, 0 370 %i1 = extractvalue { i32, i32 } %agg_right, 0 371 call void @usei32(i32 %i0) 372 br i1 %c0, label %end, label %dispatch 373 374dispatch: 375 br i1 %c1, label %left, label %right 376 377left: 378 br label %end 379 380right: 381 br label %end 382 383end: 384 %r = phi i32 [ %i0, %entry ], [ %i0, %left ], [ %i1, %right ] 385 ret i32 %r 386} 387