brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.0 KiB · 3596ef1 Raw
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