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