brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.7 KiB · cb7c0de Raw
318 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 4declare void @foo()5declare void @bar()6declare void @baz()7 8declare void @usei32(i32)9declare void @usei32i32agg({ i32, i32 })10 11; Most basic test - we explode the original aggregate into it's elements,12; and then merge them back together exactly the way they were.13; We should just return the source aggregate.14define { i32, i32 } @test0({ i32, i32 } %srcagg) {15; CHECK-LABEL: @test0(16; CHECK-NEXT:    ret { i32, i32 } [[SRCAGG:%.*]]17;18  %i0 = extractvalue { i32, i32 } %srcagg, 019  %i1 = extractvalue { i32, i32 } %srcagg, 120  %i2 = insertvalue { i32, i32 } undef, i32 %i0, 021  %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 122  ret { i32, i32 } %i323}24 25; Arrays are still aggregates26define [2 x i32] @test1([2 x i32] %srcagg) {27; CHECK-LABEL: @test1(28; CHECK-NEXT:    ret [2 x i32] [[SRCAGG:%.*]]29;30  %i0 = extractvalue [2 x i32] %srcagg, 031  %i1 = extractvalue [2 x i32] %srcagg, 132  %i2 = insertvalue [2 x i32] undef, i32 %i0, 033  %i3 = insertvalue [2 x i32] %i2, i32 %i1, 134  ret [2 x i32] %i335}36 37; Right now we don't deal with case where there are more than 2 elements.38; FIXME: should we?39define [3 x i32] @test2([3 x i32] %srcagg) {40; CHECK-LABEL: @test2(41; CHECK-NEXT:    [[I0:%.*]] = extractvalue [3 x i32] [[SRCAGG:%.*]], 042; CHECK-NEXT:    [[I1:%.*]] = extractvalue [3 x i32] [[SRCAGG]], 143; CHECK-NEXT:    [[I2:%.*]] = extractvalue [3 x i32] [[SRCAGG]], 244; CHECK-NEXT:    [[I3:%.*]] = insertvalue [3 x i32] undef, i32 [[I0]], 045; CHECK-NEXT:    [[I4:%.*]] = insertvalue [3 x i32] [[I3]], i32 [[I1]], 146; CHECK-NEXT:    [[I5:%.*]] = insertvalue [3 x i32] [[I4]], i32 [[I2]], 247; CHECK-NEXT:    ret [3 x i32] [[I5]]48;49  %i0 = extractvalue [3 x i32] %srcagg, 050  %i1 = extractvalue [3 x i32] %srcagg, 151  %i2 = extractvalue [3 x i32] %srcagg, 252  %i3 = insertvalue [3 x i32] undef, i32 %i0, 053  %i4 = insertvalue [3 x i32] %i3, i32 %i1, 154  %i5 = insertvalue [3 x i32] %i4, i32 %i2, 255  ret [3 x i32] %i556}57 58; Likewise, we only deal with a single-level aggregates.59; FIXME: should we?60define {{ i32, i32 }} @test3({{ i32, i32 }} %srcagg) {61; CHECK-LABEL: @test3(62; CHECK-NEXT:    [[I0:%.*]] = extractvalue { { i32, i32 } } [[SRCAGG:%.*]], 0, 063; CHECK-NEXT:    [[I1:%.*]] = extractvalue { { i32, i32 } } [[SRCAGG]], 0, 164; CHECK-NEXT:    [[I2:%.*]] = insertvalue { { i32, i32 } } undef, i32 [[I0]], 0, 065; CHECK-NEXT:    [[I3:%.*]] = insertvalue { { i32, i32 } } [[I2]], i32 [[I1]], 0, 166; CHECK-NEXT:    ret { { i32, i32 } } [[I3]]67;68  %i0 = extractvalue {{ i32, i32 }} %srcagg, 0, 069  %i1 = extractvalue {{ i32, i32 }} %srcagg, 0, 170  %i2 = insertvalue {{ i32, i32 }} undef, i32 %i0, 0, 071  %i3 = insertvalue {{ i32, i32 }} %i2, i32 %i1, 0, 172  ret {{ i32, i32 }} %i373}74 75; This is fine, however, all elements are on the same level76define { i32, { i32 } } @test4({ i32, { i32 } } %srcagg) {77; CHECK-LABEL: @test4(78; CHECK-NEXT:    ret { i32, { i32 } } [[SRCAGG:%.*]]79;80  %i0 = extractvalue { i32, { i32 } } %srcagg, 081  %i1 = extractvalue { i32, { i32 } } %srcagg, 182  %i2 = insertvalue { i32, { i32 } } undef, i32 %i0, 083  %i3 = insertvalue { i32, { i32 } } %i2, { i32 } %i1, 184  ret { i32, { i32 } } %i385}86 87; All element of the newly-created aggregate must come from the same base88; aggregate. Here the second element comes from some other origin.89define { i32, i32 } @negative_test5({ i32, i32 } %srcagg, i32 %replacement) {90; CHECK-LABEL: @negative_test5(91; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 092; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 093; CHECK-NEXT:    [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[REPLACEMENT:%.*]], 194; CHECK-NEXT:    ret { i32, i32 } [[I3]]95;96  %i0 = extractvalue { i32, i32 } %srcagg, 097  ; %i1 = extractvalue { i32, i32 } %srcagg, 198  %i2 = insertvalue { i32, i32 } undef, i32 %i0, 099  %i3 = insertvalue { i32, i32 } %i2, i32 %replacement, 1100  ret { i32, i32 } %i3101}102 103; Here we don't know the value of second element of %otheragg,104define { i32, i32 } @negative_test6({ i32, i32 } %srcagg, { i32, i32 } %otheragg) {105; CHECK-LABEL: @negative_test6(106; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0107; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } [[OTHERAGG:%.*]], i32 [[I0]], 0108; CHECK-NEXT:    ret { i32, i32 } [[I2]]109;110  %i0 = extractvalue { i32, i32 } %srcagg, 0111  ; %i1 = extractvalue { i32, i32 } %srcagg, 1112  %i2 = insertvalue { i32, i32 } %otheragg, i32 %i0, 0113  ret { i32, i32 } %i2114}115 116; All element of the newly-created aggregate must come from the same base117; aggregate. Here different elements come from different base aggregates.118define { i32, i32 } @negative_test7({ i32, i32 } %srcagg0, { i32, i32 } %srcagg1) {119; CHECK-LABEL: @negative_test7(120; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG0:%.*]], 0121; CHECK-NEXT:    [[I3:%.*]] = extractvalue { i32, i32 } [[SRCAGG1:%.*]], 1122; CHECK-NEXT:    [[I4:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0123; CHECK-NEXT:    [[I5:%.*]] = insertvalue { i32, i32 } [[I4]], i32 [[I3]], 1124; CHECK-NEXT:    ret { i32, i32 } [[I5]]125;126  %i0 = extractvalue { i32, i32 } %srcagg0, 0127  ; %i1 = extractvalue { i32, i32 } %srcagg0, 1128 129  ; %i2 = extractvalue { i32, i32 } %srcagg1, 0130  %i3 = extractvalue { i32, i32 } %srcagg1, 1131 132  %i4 = insertvalue { i32, i32 } undef, i32 %i0, 0133  %i5 = insertvalue { i32, i32 } %i4, i32 %i3, 1134  ret { i32, i32 } %i5135}136 137; Here the element order is swapped as compared to the base aggregate.138define { i32, i32 } @negative_test8({ i32, i32 } %srcagg) {139; CHECK-LABEL: @negative_test8(140; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0141; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[SRCAGG]], 1142; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 1143; CHECK-NEXT:    [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[I1]], 0144; CHECK-NEXT:    ret { i32, i32 } [[I3]]145;146  %i0 = extractvalue { i32, i32 } %srcagg, 0147  %i1 = extractvalue { i32, i32 } %srcagg, 1148  %i2 = insertvalue { i32, i32 } undef, i32 %i0, 1149  %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 0150  ret { i32, i32 } %i3151}152 153; Here both elements of the new aggregate come from the same element of the old aggregate.154define { i32, i32 } @negative_test9({ i32, i32 } %srcagg) {155; CHECK-LABEL: @negative_test9(156; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0157; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0158; CHECK-NEXT:    [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[I0]], 1159; CHECK-NEXT:    ret { i32, i32 } [[I3]]160;161  %i0 = extractvalue { i32, i32 } %srcagg, 0162  ; %i1 = extractvalue { i32, i32 } %srcagg, 1163  %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0164  %i3 = insertvalue { i32, i32 } %i2, i32 %i0, 1165  ret { i32, i32 } %i3166}167 168; Here the second element of the new aggregate is undef, , so we must keep this as-is, because in %srcagg it might be poison.169; FIXME: defer to noundef attribute on %srcagg170define { i32, i32 } @negative_test10({ i32, i32 } %srcagg) {171; CHECK-LABEL: @negative_test10(172; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0173; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0174; CHECK-NEXT:    ret { i32, i32 } [[I2]]175;176  %i0 = extractvalue { i32, i32 } %srcagg, 0177  ; %i1 = extractvalue { i32, i32 } %srcagg, 1178  %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0179  ret { i32, i32 } %i2180}181 182; Here the second element of the new aggregate is undef, so we must keep this as-is, because in %srcagg it might be poison.183; FIXME: defer to noundef attribute on %srcagg184define { i32, i32 } @negative_test11({ i32, i32 } %srcagg) {185; CHECK-LABEL: @negative_test11(186; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0187; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0188; CHECK-NEXT:    [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 undef, 1189; CHECK-NEXT:    ret { i32, i32 } [[I3]]190;191  %i0 = extractvalue { i32, i32 } %srcagg, 0192  ; %i1 = extractvalue { i32, i32 } %srcagg, 1193  %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0194  %i3 = insertvalue { i32, i32 } %i2, i32 undef, 1195  ret { i32, i32 } %i3196}197 198; This fold does not care whether or not intermediate instructions have extra uses.199define { i32, i32 } @test12({ i32, i32 } %srcagg) {200; CHECK-LABEL: @test12(201; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0202; CHECK-NEXT:    call void @usei32(i32 [[I0]])203; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[SRCAGG]], 1204; CHECK-NEXT:    call void @usei32(i32 [[I1]])205; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0206; CHECK-NEXT:    call void @usei32i32agg({ i32, i32 } [[I2]])207; CHECK-NEXT:    ret { i32, i32 } [[SRCAGG]]208;209  %i0 = extractvalue { i32, i32 } %srcagg, 0210  call void @usei32(i32 %i0)211  %i1 = extractvalue { i32, i32 } %srcagg, 1212  call void @usei32(i32 %i1)213  %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0214  call void @usei32i32agg({ i32, i32 } %i2)215  %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1216  ret { i32, i32 } %i3217}218 219; Even though we originally store %i1 into first element, it is later220; overwritten with %i0, so all is fine.221define { i32, i32 } @test13({ i32, i32 } %srcagg) {222; CHECK-LABEL: @test13(223; CHECK-NEXT:    ret { i32, i32 } [[SRCAGG:%.*]]224;225  %i0 = extractvalue { i32, i32 } %srcagg, 0226  %i1 = extractvalue { i32, i32 } %srcagg, 1227  %i2 = insertvalue { i32, i32 } undef, i32 %i1, 0228  %i3 = insertvalue { i32, i32 } %i2, i32 %i0, 0229  %i4 = insertvalue { i32, i32 } %i3, i32 %i1, 1230  ret { i32, i32 } %i4231}232 233; The aggregate type must match exactly between the original and recreation.234define { i32, i32 } @negative_test14({ i32, i32, i32 } %srcagg) {235; CHECK-LABEL: @negative_test14(236; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32, i32 } [[SRCAGG:%.*]], 0237; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32, i32 } [[SRCAGG]], 1238; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0239; CHECK-NEXT:    [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[I1]], 1240; CHECK-NEXT:    ret { i32, i32 } [[I3]]241;242  %i0 = extractvalue { i32, i32, i32 } %srcagg, 0243  %i1 = extractvalue { i32, i32, i32 } %srcagg, 1244  %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0245  %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1246  ret { i32, i32 } %i3247}248define { i32, i32 } @negative_test15({ i32, {i32} } %srcagg) {249; CHECK-LABEL: @negative_test15(250; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, { i32 } } [[SRCAGG:%.*]], 0251; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, { i32 } } [[SRCAGG]], 1, 0252; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0253; CHECK-NEXT:    [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[I1]], 1254; CHECK-NEXT:    ret { i32, i32 } [[I3]]255;256  %i0 = extractvalue { i32, {i32} } %srcagg, 0257  %i1 = extractvalue { i32, {i32} } %srcagg, 1, 0258  %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0259  %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1260  ret { i32, i32 } %i3261}262 263; Just because there are predecessors doesn't mean we should look into them.264define { i32, i32 } @test16({ i32, i32 } %srcagg) {265; CHECK-LABEL: @test16(266; CHECK-NEXT:  entry:267; CHECK-NEXT:    br label [[END:%.*]]268; CHECK:       end:269; CHECK-NEXT:    ret { i32, i32 } [[SRCAGG:%.*]]270;271entry:272  br label %end273end:274  %i0 = extractvalue { i32, i32 } %srcagg, 0275  %i1 = extractvalue { i32, i32 } %srcagg, 1276  %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0277  %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1278  ret { i32, i32 } %i3279}280 281; Again, we should first try to perform local reasoning, without looking to predecessors.282define { i32, i32 } @test17({ i32, i32 } %srcagg0, { i32, i32 } %srcagg1, i1 %c) {283; CHECK-LABEL: @test17(284; CHECK-NEXT:  entry:285; CHECK-NEXT:    br i1 [[C:%.*]], label [[INTERMEDIATE:%.*]], label [[END:%.*]]286; CHECK:       intermediate:287; CHECK-NEXT:    br label [[END]]288; CHECK:       end:289; CHECK-NEXT:    [[SRCAGG_PHI:%.*]] = phi { i32, i32 } [ [[SRCAGG0:%.*]], [[ENTRY:%.*]] ], [ [[SRCAGG1:%.*]], [[INTERMEDIATE]] ]290; CHECK-NEXT:    ret { i32, i32 } [[SRCAGG_PHI]]291;292entry:293  br i1 %c, label %intermediate, label %end294intermediate:295  br label %end296end:297  %srcagg.phi = phi { i32, i32 } [ %srcagg0, %entry ], [ %srcagg1, %intermediate ]298  %i0 = extractvalue { i32, i32 } %srcagg.phi, 0299  %i1 = extractvalue { i32, i32 } %srcagg.phi, 1300  %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0301  %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1302  ret { i32, i32 } %i3303}304 305; Like test2 but with a poison base.306define [3 x i32] @poison_base([3 x i32] %srcagg) {307; CHECK-LABEL: @poison_base(308; CHECK-NEXT:    ret [3 x i32] [[SRCAGG:%.*]]309;310  %i0 = extractvalue [3 x i32] %srcagg, 0311  %i1 = extractvalue [3 x i32] %srcagg, 1312  %i2 = extractvalue [3 x i32] %srcagg, 2313  %i3 = insertvalue [3 x i32] poison, i32 %i0, 0314  %i4 = insertvalue [3 x i32] %i3, i32 %i1, 1315  %i5 = insertvalue [3 x i32] %i4, i32 %i2, 2316  ret [3 x i32] %i5317}318