358 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 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]], 019; CHECK-NEXT: ret { i32, i32 } [[R]]20;21entry:22 br i1 %c, label %left, label %right23 24left:25 %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 026 br label %end27 28right:29 %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 030 br label %end31 32end:33 %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]34 ret { i32, i32 } %r35}36 37; But only if the insertvalues have no extra uses38define { 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:%.*]], 044; 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:%.*]], 048; 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 %right55 56left:57 %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 058 call void @usei32i32agg({ i32, i32 } %i0 )59 br label %end60 61right:62 %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 063 br label %end64 65end:66 %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]67 ret { i32, i32 } %r68}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:%.*]], 075; CHECK-NEXT: br label [[END:%.*]]76; CHECK: right:77; CHECK-NEXT: [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 078; 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 %right86 87left:88 %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 089 br label %end90 91right:92 %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 093 call void @usei32i32agg({ i32, i32 } %i1 )94 br label %end95 96end:97 %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]98 ret { i32, i32 } %r99}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:%.*]], 0106; 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:%.*]], 0110; 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 %right118 119left:120 %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0121 call void @usei32i32agg({ i32, i32 } %i0 )122 br label %end123 124right:125 %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0126 call void @usei32i32agg({ i32, i32 } %i1 )127 br label %end128 129end:130 %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]131 ret { i32, i32 } %r132}133 134; Here, we only need a PHI for base aggregate135define { 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:%.*]], 0146; CHECK-NEXT: ret { i32, i32 } [[R]]147;148entry:149 br i1 %c, label %left, label %right150 151left:152 %i0 = insertvalue { i32, i32 } %agg_left, i32 %val, 0153 br label %end154 155right:156 %i1 = insertvalue { i32, i32 } %agg_right, i32 %val, 0157 br label %end158 159end:160 %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]161 ret { i32, i32 } %r162}163 164; Here, we need a PHI for both the base and the inserted value165define { 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]], 0177; CHECK-NEXT: ret { i32, i32 } [[R]]178;179entry:180 br i1 %c, label %left, label %right181 182left:183 %i0 = insertvalue { i32, i32 } %agg_left, i32 %val_left, 0184 br label %end185 186right:187 %i1 = insertvalue { i32, i32 } %agg_right, i32 %val_right, 0188 br label %end189 190end:191 %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]192 ret { i32, i32 } %r193}194 195; But the indices must match196define { 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:%.*]], 0202; CHECK-NEXT: br label [[END:%.*]]203; CHECK: right:204; CHECK-NEXT: [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 1205; 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 %right212 213left:214 %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0215 br label %end216 217right:218 %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 1219 br label %end220 221end:222 %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]223 ret { i32, i32 } %r224}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, 0238; CHECK-NEXT: ret { { i32, i32 }, { i32, i32 } } [[R]]239;240entry:241 br i1 %c, label %left, label %right242 243left:244 %i0 = insertvalue {{ i32, i32 }, { i32, i32 }} %agg, i32 %val_left, 0, 0245 br label %end246 247right:248 %i1 = insertvalue {{ i32, i32 }, { i32, i32 }} %agg, i32 %val_right, 0, 0249 br label %end250 251end:252 %r = phi {{ i32, i32 }, { i32, i32 }} [ %i0, %left ], [ %i1, %right ]253 ret {{ i32, i32 }, { i32, i32 }} %r254}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, 0263; CHECK-NEXT: br label [[END:%.*]]264; CHECK: right:265; CHECK-NEXT: [[I1:%.*]] = insertvalue { { i32, i32 }, { i32, i32 } } [[AGG]], i32 [[VAL_RIGHT:%.*]], 0, 1266; 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 %right273 274left:275 %i0 = insertvalue {{ i32, i32 }, { i32, i32 }} %agg, i32 %val_left, 0, 0276 br label %end277 278right:279 %i1 = insertvalue {{ i32, i32 }, { i32, i32 }} %agg, i32 %val_right, 0, 1280 br label %end281 282end:283 %r = phi {{ i32, i32 }, { i32, i32 }} [ %i0, %left ], [ %i1, %right ]284 ret {{ i32, i32 }, { i32, i32 }} %r285}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 itself288define { 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]], 0301; CHECK-NEXT: ret { i32, i32 } [[R]]302;303entry:304 %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0305 %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0306 br i1 %c0, label %end, label %dispatch307 308dispatch:309 br i1 %c1, label %left, label %right310 311left:312 br label %end313 314right:315 br label %end316 317end:318 %r = phi { i32, i32 } [ %i0, %entry ], [ %i0, %left ], [ %i1, %right ]319 ret { i32, i32 } %r320}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:%.*]], 0326; CHECK-NEXT: [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 0327; 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, 0341 %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0342 call void @usei32i32agg({ i32, i32 } %i0)343 br i1 %c0, label %end, label %dispatch344 345dispatch:346 br i1 %c1, label %left, label %right347 348left:349 br label %end350 351right:352 br label %end353 354end:355 %r = phi { i32, i32 } [ %i0, %entry ], [ %i0, %left ], [ %i1, %right ]356 ret { i32, i32 } %r357}358