brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.7 KiB · 26893c1 Raw
519 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 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]], 019; CHECK-NEXT:    ret i32 [[R]]20;21entry:22  br i1 %c, label %left, label %right23 24left:25  %i0 = extractvalue { i32, i32 } %agg_left, 026  br label %end27 28right:29  %i1 = extractvalue { i32, i32 } %agg_right, 030  br label %end31 32end:33  %r = phi i32 [ %i0, %left ], [ %i1, %right ]34  ret i32 %r35}36 37; But only if the extractvalues have no extra uses38define 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:%.*]], 044; 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:%.*]], 048; 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 %right55 56left:57  %i0 = extractvalue { i32, i32 } %agg_left, 058  call void  @usei32(i32 %i0)59  br label %end60 61right:62  %i1 = extractvalue { i32, i32 } %agg_right, 063  br label %end64 65end:66  %r = phi i32 [ %i0, %left ], [ %i1, %right ]67  ret i32 %r68}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:%.*]], 075; CHECK-NEXT:    br label [[END:%.*]]76; CHECK:       right:77; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 078; 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 %right86 87left:88  %i0 = extractvalue { i32, i32 } %agg_left, 089  br label %end90 91right:92  %i1 = extractvalue { i32, i32 } %agg_right, 093  call void  @usei32(i32 %i1)94  br label %end95 96end:97  %r = phi i32 [ %i0, %left ], [ %i1, %right ]98  ret i32 %r99}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:%.*]], 0106; 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:%.*]], 0110; 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 %right118 119left:120  %i0 = extractvalue { i32, i32 } %agg_left, 0121  call void  @usei32(i32 %i0)122  br label %end123 124right:125  %i1 = extractvalue { i32, i32 } %agg_right, 0126  call void  @usei32(i32 %i1)127  br label %end128 129end:130  %r = phi i32 [ %i0, %left ], [ %i1, %right ]131  ret i32 %r132}133 134; But the indices must match135define 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:%.*]], 0141; CHECK-NEXT:    br label [[END:%.*]]142; CHECK:       right:143; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 1144; 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 %right151 152left:153  %i0 = extractvalue { i32, i32 } %agg_left, 0154  br label %end155 156right:157  %i1 = extractvalue { i32, i32 } %agg_right, 1158  br label %end159 160end:161  %r = phi i32 [ %i0, %left ], [ %i1, %right ]162  ret i32 %r163}164 165; More complex aggregates are fine, too, as long as indices 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, 0177; CHECK-NEXT:    ret i32 [[R]]178;179entry:180  br i1 %c, label %left, label %right181 182left:183  %i0 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_left, 0, 0184  br label %end185 186right:187  %i1 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_right, 0, 0188  br label %end189 190end:191  %r = phi i32 [ %i0, %left ], [ %i1, %right ]192  ret i32 %r193}194 195; The indices 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, 0202; CHECK-NEXT:    br label [[END:%.*]]203; CHECK:       right:204; CHECK-NEXT:    [[I1:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_RIGHT:%.*]], 0, 1205; 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 %right212 213left:214  %i0 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_left, 0, 0215  br label %end216 217right:218  %i1 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_right, 0, 1219  br label %end220 221end:222  %r = phi i32 [ %i0, %left ], [ %i1, %right ]223  ret i32 %r224}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, 0231; CHECK-NEXT:    br label [[END:%.*]]232; CHECK:       right:233; CHECK-NEXT:    [[I1:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_RIGHT:%.*]], 1, 0234; 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 %right241 242left:243  %i0 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_left, 0, 0244  br label %end245 246right:247  %i1 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_right, 1, 0248  br label %end249 250end:251  %r = phi i32 [ %i0, %left ], [ %i1, %right ]252  ret i32 %r253}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, 0260; CHECK-NEXT:    br label [[END:%.*]]261; CHECK:       right:262; CHECK-NEXT:    [[I1:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_RIGHT:%.*]], 1, 1263; 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 %right270 271left:272  %i0 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_left, 0, 0273  br label %end274 275right:276  %i1 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_right, 1, 1277  br label %end278 279end:280  %r = phi i32 [ %i0, %left ], [ %i1, %right ]281  ret i32 %r282}283 284; Also, unlike PHI-of-insertvalues, here the base aggregates of extractvalue285; can have different types, and just checking the indices 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:%.*]], 0292; CHECK-NEXT:    br label [[END:%.*]]293; CHECK:       right:294; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, { i32, i32 } } [[AGG_RIGHT:%.*]], 0295; 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 %right302 303left:304  %i0 = extractvalue { i32, i32 } %agg_left, 0305  br label %end306 307right:308  %i1 = extractvalue { i32, { i32, i32 } } %agg_right, 0309  br label %end310 311end:312  %r = phi i32 [ %i0, %left ], [ %i1, %right ]313  ret i32 %r314}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 itself317define 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]], 0330; CHECK-NEXT:    ret i32 [[R]]331;332entry:333  %i0 = extractvalue { i32, i32 } %agg_left, 0334  %i1 = extractvalue { i32, i32 } %agg_right, 0335  br i1 %c0, label %end, label %dispatch336 337dispatch:338  br i1 %c1, label %left, label %right339 340left:341  br label %end342 343right:344  br label %end345 346end:347  %r = phi i32 [ %i0, %entry ], [ %i0, %left ], [ %i1, %right ]348  ret i32 %r349}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:%.*]], 0355; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 0356; 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, 0370  %i1 = extractvalue { i32, i32 } %agg_right, 0371  call void @usei32(i32 %i0)372  br i1 %c0, label %end, label %dispatch373 374dispatch:375  br i1 %c1, label %left, label %right376 377left:378  br label %end379 380right:381  br label %end382 383end:384  %r = phi i32 [ %i0, %entry ], [ %i0, %left ], [ %i1, %right ]385  ret i32 %r386}387 388define i32 @extractvalue_of_constant_phi(i1 %c) {389; CHECK-LABEL: @extractvalue_of_constant_phi(390; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]391; CHECK:       if:392; CHECK-NEXT:    br label [[JOIN:%.*]]393; CHECK:       else:394; CHECK-NEXT:    br label [[JOIN]]395; CHECK:       join:396; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ 1, [[IF]] ], [ 3, [[ELSE]] ]397; CHECK-NEXT:    ret i32 [[PHI]]398;399  br i1 %c, label %if, label %else400 401if:402  br label %join403 404else:405  br label %join406 407join:408  %phi = phi { i32, i32 } [ { i32 1, i32 2 }, %if ], [ { i32 3, i32 4 }, %else ]409  %ev = extractvalue { i32, i32 } %phi, 0410  ret i32 %ev411}412 413define i32 @extractvalue_of_one_constant_phi(i1 %c, { i32, i32 } %arg) {414; CHECK-LABEL: @extractvalue_of_one_constant_phi(415; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]416; CHECK:       if:417; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { i32, i32 } [[ARG:%.*]], 0418; CHECK-NEXT:    br label [[JOIN:%.*]]419; CHECK:       else:420; CHECK-NEXT:    br label [[JOIN]]421; CHECK:       join:422; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[TMP1]], [[IF]] ], [ 3, [[ELSE]] ]423; CHECK-NEXT:    ret i32 [[PHI]]424;425  br i1 %c, label %if, label %else426 427if:428  br label %join429 430else:431  br label %join432 433join:434  %phi = phi { i32, i32 } [ %arg, %if ], [ { i32 3, i32 4 }, %else ]435  %ev = extractvalue { i32, i32 } %phi, 0436  ret i32 %ev437}438 439define i32 @extractvalue_of_constant_phi_multi_index(i1 %c) {440; CHECK-LABEL: @extractvalue_of_constant_phi_multi_index(441; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]442; CHECK:       if:443; CHECK-NEXT:    br label [[JOIN:%.*]]444; CHECK:       else:445; CHECK-NEXT:    br label [[JOIN]]446; CHECK:       join:447; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ 3, [[IF]] ], [ 6, [[ELSE]] ]448; CHECK-NEXT:    ret i32 [[PHI]]449;450  br i1 %c, label %if, label %else451 452if:453  br label %join454 455else:456  br label %join457 458join:459  %phi = phi { i32, { i32, i32 } } [ { i32 1, { i32, i32 } { i32 2, i32 3 } }, %if ], [ { i32 4, { i32, i32 } { i32 5, i32 6 } }, %else ]460  %ev = extractvalue { i32, { i32, i32 } } %phi, 1, 1461  ret i32 %ev462}463 464define i32 @extractvalue_of_one_constant_phi_multi_index(i1 %c, { i32, { i32, i32 } } %arg) {465; CHECK-LABEL: @extractvalue_of_one_constant_phi_multi_index(466; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]467; CHECK:       if:468; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { i32, { i32, i32 } } [[ARG:%.*]], 1, 1469; CHECK-NEXT:    br label [[JOIN:%.*]]470; CHECK:       else:471; CHECK-NEXT:    br label [[JOIN]]472; CHECK:       join:473; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[TMP1]], [[IF]] ], [ 6, [[ELSE]] ]474; CHECK-NEXT:    ret i32 [[PHI]]475;476  br i1 %c, label %if, label %else477 478if:479  br label %join480 481else:482  br label %join483 484join:485  %phi = phi { i32, { i32, i32 } } [ %arg, %if ], [ { i32 4, { i32, i32 } { i32 5, i32 6 } }, %else ]486  %ev = extractvalue { i32, { i32, i32 } } %phi, 1, 1487  ret i32 %ev488}489 490define i32 @extractvalue_of_constant_phi_multiuse(i1 %c) {491; CHECK-LABEL: @extractvalue_of_constant_phi_multiuse(492; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]493; CHECK:       if:494; CHECK-NEXT:    br label [[JOIN:%.*]]495; CHECK:       else:496; CHECK-NEXT:    br label [[JOIN]]497; CHECK:       join:498; CHECK-NEXT:    [[PHI:%.*]] = phi { i32, i32 } [ { i32 1, i32 2 }, [[IF]] ], [ { i32 3, i32 4 }, [[ELSE]] ]499; CHECK-NEXT:    [[EV0:%.*]] = extractvalue { i32, i32 } [[PHI]], 0500; CHECK-NEXT:    [[EV1:%.*]] = extractvalue { i32, i32 } [[PHI]], 1501; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[EV0]], [[EV1]]502; CHECK-NEXT:    ret i32 [[ADD]]503;504  br i1 %c, label %if, label %else505 506if:507  br label %join508 509else:510  br label %join511 512join:513  %phi = phi { i32, i32 } [ { i32 1, i32 2 }, %if ], [ { i32 3, i32 4 }, %else ]514  %ev0 = extractvalue { i32, i32 } %phi, 0515  %ev1 = extractvalue { i32, i32 } %phi, 1516  %add = add i32 %ev0, %ev1517  ret i32 %add518}519