354 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 4declare {ptr, i64} @bar(i64)5 6; Basic test.7define {ptr, i64} @test1(i1 %cond1, ptr %p1, ptr %p2) {8; CHECK-LABEL: define { ptr, i64 } @test1(9; CHECK-SAME: i1 [[COND1:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]]) {10; CHECK-NEXT: br i1 [[COND1]], label %[[BBB1:.*]], label %[[BBB2:.*]]11; CHECK: [[BBB1]]:12; CHECK-NEXT: [[CALL1:%.*]] = call { ptr, i64 } @bar(i64 0)13; CHECK-NEXT: br label %[[EXIT:.*]]14; CHECK: [[BBB2]]:15; CHECK-NEXT: [[VAL21:%.*]] = load ptr, ptr [[P1]], align 816; CHECK-NEXT: [[VAL22:%.*]] = load i64, ptr [[P2]], align 417; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { ptr, i64 } poison, ptr [[VAL21]], 018; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { ptr, i64 } [[TMP1]], i64 [[VAL22]], 119; CHECK-NEXT: br label %[[EXIT]]20; CHECK: [[EXIT]]:21; CHECK-NEXT: [[RES_MERGED:%.*]] = phi { ptr, i64 } [ [[CALL1]], %[[BBB1]] ], [ [[TMP2]], %[[BBB2]] ]22; CHECK-NEXT: ret { ptr, i64 } [[RES_MERGED]]23;24 br i1 %cond1, label %bbb1, label %bbb225 26bbb1:27 %call1 = call {ptr, i64} @bar(i64 0)28 %val11 = extractvalue { ptr, i64 } %call1, 029 %val12 = extractvalue { ptr, i64 } %call1, 130 br label %exit31 32bbb2:33 %val21 = load ptr, ptr %p134 %val22 = load i64, ptr %p235 br label %exit36 37exit:38 %val1 = phi ptr [%val11, %bbb1], [%val21, %bbb2]39 %val2 = phi i64 [%val12, %bbb1], [%val22, %bbb2]40 %tmp = insertvalue { ptr, i64 } poison, ptr %val1, 041 %res = insertvalue { ptr, i64 } %tmp, i64 %val2, 142 ret {ptr, i64} %res43}44 45; Test with more predecessors.46define {ptr, i64} @test2(i1 %cond1, i1 %cond2, ptr %p1, ptr %p2) {47; CHECK-LABEL: define { ptr, i64 } @test2(48; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]]) {49; CHECK-NEXT: br i1 [[COND1]], label %[[BBB1:.*]], label %[[BBB4:.*]]50; CHECK: [[BBB1]]:51; CHECK-NEXT: br i1 [[COND2]], label %[[BBB2:.*]], label %[[BBB3:.*]]52; CHECK: [[BBB2]]:53; CHECK-NEXT: [[CALL1:%.*]] = call { ptr, i64 } @bar(i64 0)54; CHECK-NEXT: br label %[[EXIT:.*]]55; CHECK: [[BBB3]]:56; CHECK-NEXT: [[CALL2:%.*]] = call { ptr, i64 } @bar(i64 1)57; CHECK-NEXT: br label %[[EXIT]]58; CHECK: [[BBB4]]:59; CHECK-NEXT: [[VAL31:%.*]] = load ptr, ptr [[P1]], align 860; CHECK-NEXT: [[VAL32:%.*]] = load i64, ptr [[P2]], align 461; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { ptr, i64 } poison, ptr [[VAL31]], 062; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { ptr, i64 } [[TMP1]], i64 [[VAL32]], 163; CHECK-NEXT: br label %[[EXIT]]64; CHECK: [[EXIT]]:65; CHECK-NEXT: [[RES_MERGED:%.*]] = phi { ptr, i64 } [ [[CALL1]], %[[BBB2]] ], [ [[CALL2]], %[[BBB3]] ], [ [[TMP2]], %[[BBB4]] ]66; CHECK-NEXT: ret { ptr, i64 } [[RES_MERGED]]67;68 br i1 %cond1, label %bbb1, label %bbb469 70bbb1:71 br i1 %cond2, label %bbb2, label %bbb372 73bbb2:74 %call1 = call {ptr, i64} @bar(i64 0)75 %val11 = extractvalue { ptr, i64 } %call1, 076 %val12 = extractvalue { ptr, i64 } %call1, 177 br label %exit78 79bbb3:80 %call2 = call {ptr, i64} @bar(i64 1)81 %val21 = extractvalue { ptr, i64 } %call2, 082 %val22 = extractvalue { ptr, i64 } %call2, 183 br label %exit84 85bbb4:86 %val31 = load ptr, ptr %p187 %val32 = load i64, ptr %p288 br label %exit89 90exit:91 %val1 = phi ptr [%val11, %bbb2], [%val21, %bbb3], [%val31, %bbb4]92 %val2 = phi i64 [%val12, %bbb2], [%val22, %bbb3], [%val32, %bbb4]93 %tmp = insertvalue { ptr, i64 } poison, ptr %val1, 094 %res = insertvalue { ptr, i64 } %tmp, i64 %val2, 195 ret {ptr, i64} %res96}97 98; Test with multiple PHI instructions.99define {ptr, i64} @test3(i1 %cond1, i1 %cond2, ptr %val31, i64 %val32) {100; CHECK-LABEL: define { ptr, i64 } @test3(101; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], ptr [[VAL31:%.*]], i64 [[VAL32:%.*]]) {102; CHECK-NEXT: br i1 [[COND1]], label %[[BBB1:.*]], label %[[BBB4:.*]]103; CHECK: [[BBB1]]:104; CHECK-NEXT: br i1 [[COND2]], label %[[BBB2:.*]], label %[[BBB3:.*]]105; CHECK: [[BBB2]]:106; CHECK-NEXT: [[CALL1:%.*]] = call { ptr, i64 } @bar(i64 0)107; CHECK-NEXT: br label %[[EXIT:.*]]108; CHECK: [[BBB3]]:109; CHECK-NEXT: [[CALL2:%.*]] = call { ptr, i64 } @bar(i64 1)110; CHECK-NEXT: br label %[[BBB5:.*]]111; CHECK: [[BBB4]]:112; CHECK-NEXT: [[CALL3:%.*]] = call { ptr, i64 } @bar(i64 2)113; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { ptr, i64 } poison, ptr [[VAL31]], 0114; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { ptr, i64 } [[TMP1]], i64 [[VAL32]], 1115; CHECK-NEXT: br label %[[BBB5]]116; CHECK: [[BBB5]]:117; CHECK-NEXT: [[DOTMERGED:%.*]] = phi { ptr, i64 } [ [[CALL2]], %[[BBB3]] ], [ [[TMP2]], %[[BBB4]] ]118; CHECK-NEXT: br label %[[EXIT]]119; CHECK: [[EXIT]]:120; CHECK-NEXT: [[RES_MERGED:%.*]] = phi { ptr, i64 } [ [[CALL1]], %[[BBB2]] ], [ [[DOTMERGED]], %[[BBB5]] ]121; CHECK-NEXT: ret { ptr, i64 } [[RES_MERGED]]122;123 br i1 %cond1, label %bbb1, label %bbb4124 125bbb1:126 br i1 %cond2, label %bbb2, label %bbb3127 128bbb2:129 %call1 = call {ptr, i64} @bar(i64 0)130 %val11 = extractvalue { ptr, i64 } %call1, 0131 %val12 = extractvalue { ptr, i64 } %call1, 1132 br label %exit133 134bbb3:135 %call2 = call {ptr, i64} @bar(i64 1)136 %val21 = extractvalue { ptr, i64 } %call2, 0137 %val22 = extractvalue { ptr, i64 } %call2, 1138 br label %bbb5139 140bbb4:141 %call3 = call {ptr, i64} @bar(i64 2)142 br label %bbb5143 144bbb5:145 %val41 = phi ptr [%val21, %bbb3], [%val31, %bbb4]146 %val42 = phi i64 [%val22, %bbb3], [%val32, %bbb4]147 br label %exit148 149exit:150 %val1 = phi ptr [%val11, %bbb2], [%val41, %bbb5]151 %val2 = phi i64 [%val12, %bbb2], [%val42, %bbb5]152 %tmp = insertvalue { ptr, i64 } poison, ptr %val1, 0153 %res = insertvalue { ptr, i64 } %tmp, i64 %val2, 1154 ret {ptr, i64} %res155}156 157; Negative test, bbb4 has multiple successors, so we don't add insertvalue to it.158define {ptr, i64} @test4(i1 %cond1, i1 %cond2, ptr %p1, ptr %p2) {159; CHECK-LABEL: define { ptr, i64 } @test4(160; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]]) {161; CHECK-NEXT: br i1 [[COND1]], label %[[BBB1:.*]], label %[[BBB4:.*]]162; CHECK: [[BBB1]]:163; CHECK-NEXT: br i1 [[COND2]], label %[[BBB2:.*]], label %[[BBB3:.*]]164; CHECK: [[BBB2]]:165; CHECK-NEXT: [[CALL1:%.*]] = call { ptr, i64 } @bar(i64 0)166; CHECK-NEXT: [[VAL11:%.*]] = extractvalue { ptr, i64 } [[CALL1]], 0167; CHECK-NEXT: [[VAL12:%.*]] = extractvalue { ptr, i64 } [[CALL1]], 1168; CHECK-NEXT: br label %[[EXIT:.*]]169; CHECK: [[BBB3]]:170; CHECK-NEXT: [[CALL2:%.*]] = call { ptr, i64 } @bar(i64 1)171; CHECK-NEXT: [[VAL21:%.*]] = extractvalue { ptr, i64 } [[CALL2]], 0172; CHECK-NEXT: [[VAL22:%.*]] = extractvalue { ptr, i64 } [[CALL2]], 1173; CHECK-NEXT: br label %[[EXIT]]174; CHECK: [[BBB4]]:175; CHECK-NEXT: [[VAL31:%.*]] = load ptr, ptr [[P1]], align 8176; CHECK-NEXT: [[VAL32:%.*]] = load i64, ptr [[P2]], align 4177; CHECK-NEXT: [[COND3_NOT:%.*]] = icmp eq i64 [[VAL32]], 0178; CHECK-NEXT: br i1 [[COND3_NOT]], label %[[EXIT]], label %[[BBB4]]179; CHECK: [[EXIT]]:180; CHECK-NEXT: [[VAL1:%.*]] = phi ptr [ [[VAL11]], %[[BBB2]] ], [ [[VAL21]], %[[BBB3]] ], [ [[VAL31]], %[[BBB4]] ]181; CHECK-NEXT: [[VAL2:%.*]] = phi i64 [ [[VAL12]], %[[BBB2]] ], [ [[VAL22]], %[[BBB3]] ], [ [[VAL32]], %[[BBB4]] ]182; CHECK-NEXT: [[TMP:%.*]] = insertvalue { ptr, i64 } poison, ptr [[VAL1]], 0183; CHECK-NEXT: [[RES:%.*]] = insertvalue { ptr, i64 } [[TMP]], i64 [[VAL2]], 1184; CHECK-NEXT: ret { ptr, i64 } [[RES]]185;186 br i1 %cond1, label %bbb1, label %bbb4187 188bbb1:189 br i1 %cond2, label %bbb2, label %bbb3190 191bbb2:192 %call1 = call {ptr, i64} @bar(i64 0)193 %val11 = extractvalue { ptr, i64 } %call1, 0194 %val12 = extractvalue { ptr, i64 } %call1, 1195 br label %exit196 197bbb3:198 %call2 = call {ptr, i64} @bar(i64 1)199 %val21 = extractvalue { ptr, i64 } %call2, 0200 %val22 = extractvalue { ptr, i64 } %call2, 1201 br label %exit202 203bbb4:204 %val31 = load ptr, ptr %p1205 %val32 = load i64, ptr %p2206 %cond3 = icmp ne i64 %val32, 0207 br i1 %cond3, label %bbb4, label %exit208 209exit:210 %val1 = phi ptr [%val11, %bbb2], [%val21, %bbb3], [%val31, %bbb4]211 %val2 = phi i64 [%val12, %bbb2], [%val22, %bbb3], [%val32, %bbb4]212 %tmp = insertvalue { ptr, i64 } poison, ptr %val1, 0213 %res = insertvalue { ptr, i64 } %tmp, i64 %val2, 1214 ret {ptr, i64} %res215}216 217; Negative test, %.elt2 is defined in bb %end, it can't be accessed from %then,218; so we can't add insertvalue to %then.219define { ptr, i64 } @test5({ ptr, i64 } %src, ptr %pointer, i1 %cond) {220; CHECK-LABEL: define { ptr, i64 } @test5(221; CHECK-SAME: { ptr, i64 } [[SRC:%.*]], ptr [[POINTER:%.*]], i1 [[COND:%.*]]) {222; CHECK-NEXT: [[ENTRY:.*:]]223; CHECK-NEXT: br i1 [[COND]], label %[[THEN:.*]], label %[[ELSE:.*]]224; CHECK: [[THEN]]:225; CHECK-NEXT: store ptr null, ptr [[POINTER]], align 8226; CHECK-NEXT: br label %[[END:.*]]227; CHECK: [[ELSE]]:228; CHECK-NEXT: [[DOTELT1:%.*]] = extractvalue { ptr, i64 } [[SRC]], 0229; CHECK-NEXT: br label %[[END]]230; CHECK: [[END]]:231; CHECK-NEXT: [[TMP6:%.*]] = phi ptr [ [[DOTELT1]], %[[ELSE]] ], [ null, %[[THEN]] ]232; CHECK-NEXT: [[DOTELT2:%.*]] = extractvalue { ptr, i64 } [[SRC]], 1233; CHECK-NEXT: [[TMP7:%.*]] = insertvalue { ptr, i64 } zeroinitializer, ptr [[TMP6]], 0234; CHECK-NEXT: [[TMP8:%.*]] = insertvalue { ptr, i64 } [[TMP7]], i64 [[DOTELT2]], 1235; CHECK-NEXT: ret { ptr, i64 } [[TMP8]]236;237entry:238 br i1 %cond, label %then, label %else239 240then:241 store ptr null, ptr %pointer, align 8242 br label %end243 244else:245 %.elt1 = extractvalue { ptr, i64 } %src, 0246 br label %end247 248end:249 %elt = phi ptr [ %.elt1, %else ], [ null, %then ]250 %.elt2 = extractvalue { ptr, i64 } %src, 1251 %agg1 = insertvalue { ptr, i64 } zeroinitializer, ptr %elt, 0252 %res = insertvalue { ptr, i64 } %agg1, i64 %.elt2, 1253 ret { ptr, i64 } %res254}255 256; Negative test, we should not add insertvalue to inner loops.257define { i64, ptr } @test6({ i64, ptr } %agg1, i1 %cond1, i1 %cond2, { i64, ptr } %agg3) {258; CHECK-LABEL: define { i64, ptr } @test6(259; CHECK-SAME: { i64, ptr } [[AGG1:%.*]], i1 [[COND1:%.*]], i1 [[COND2:%.*]], { i64, ptr } [[AGG3:%.*]]) {260; CHECK-NEXT: [[ENTRY:.*]]:261; CHECK-NEXT: [[F10:%.*]] = extractvalue { i64, ptr } [[AGG1]], 0262; CHECK-NEXT: [[F11:%.*]] = extractvalue { i64, ptr } [[AGG1]], 1263; CHECK-NEXT: br label %[[HEADER:.*]]264; CHECK: [[HEADER]]:265; CHECK-NEXT: [[DOTSROA_01_0:%.*]] = phi i64 [ [[F10]], %[[ENTRY]] ], [ [[DOTSROA_01_1:%.*]], %[[LATCH:.*]] ]266; CHECK-NEXT: [[DOTSROA_3_0:%.*]] = phi ptr [ [[F11]], %[[ENTRY]] ], [ [[DOTSROA_3_1:%.*]], %[[LATCH]] ]267; CHECK-NEXT: br i1 [[COND1]], label %[[CHECK:.*]], label %[[EXIT:.*]]268; CHECK: [[CHECK]]:269; CHECK-NEXT: br i1 [[COND2]], label %[[THEN:.*]], label %[[ELSE:.*]]270; CHECK: [[THEN]]:271; CHECK-NEXT: [[F30:%.*]] = extractvalue { i64, ptr } [[AGG3]], 0272; CHECK-NEXT: [[F31:%.*]] = extractvalue { i64, ptr } [[AGG3]], 1273; CHECK-NEXT: br label %[[LATCH]]274; CHECK: [[ELSE]]:275; CHECK-NEXT: br label %[[LATCH]]276; CHECK: [[LATCH]]:277; CHECK-NEXT: [[DOTSROA_01_1]] = phi i64 [ [[F30]], %[[THEN]] ], [ [[DOTSROA_01_0]], %[[ELSE]] ]278; CHECK-NEXT: [[DOTSROA_3_1]] = phi ptr [ [[F31]], %[[THEN]] ], [ [[DOTSROA_3_0]], %[[ELSE]] ]279; CHECK-NEXT: br label %[[HEADER]]280; CHECK: [[EXIT]]:281; CHECK-NEXT: [[DOTFCA_0_INSERT:%.*]] = insertvalue { i64, ptr } zeroinitializer, i64 [[DOTSROA_01_0]], 0282; CHECK-NEXT: [[DOTFCA_1_INSERT:%.*]] = insertvalue { i64, ptr } [[DOTFCA_0_INSERT]], ptr [[DOTSROA_3_0]], 1283; CHECK-NEXT: ret { i64, ptr } [[DOTFCA_1_INSERT]]284;285entry:286 %f10 = extractvalue { i64, ptr } %agg1, 0287 %f11 = extractvalue { i64, ptr } %agg1, 1288 br label %header289 290header:291 %.sroa.01.0 = phi i64 [ %f10, %entry ], [ %.sroa.01.1, %latch ]292 %.sroa.3.0 = phi ptr [ %f11, %entry ], [ %.sroa.3.1, %latch ]293 br i1 %cond1, label %check, label %exit294 295check:296 br i1 %cond2, label %then, label %else297 298then:299 %f30 = extractvalue { i64, ptr } %agg3, 0300 %f31 = extractvalue { i64, ptr } %agg3, 1301 br label %latch302 303else:304 br label %latch305 306latch:307 %.sroa.01.1 = phi i64 [ %f30, %then ], [ %.sroa.01.0, %else ]308 %.sroa.3.1 = phi ptr [ %f31, %then ], [ %.sroa.3.0, %else ]309 br label %header310 311exit:312 %.fca.0.insert = insertvalue { i64, ptr } zeroinitializer, i64 %.sroa.01.0, 0313 %.fca.1.insert = insertvalue { i64, ptr } %.fca.0.insert, ptr %.sroa.3.0, 1314 ret { i64, ptr } %.fca.1.insert315}316 317; Negative test, don't construct constant aggregate.318define {ptr, i64} @test7(i1 %cond1, ptr %p1) {319; CHECK-LABEL: define { ptr, i64 } @test7(320; CHECK-SAME: i1 [[COND1:%.*]], ptr [[P1:%.*]]) {321; CHECK-NEXT: br i1 [[COND1]], label %[[BBB1:.*]], label %[[BBB2:.*]]322; CHECK: [[BBB1]]:323; CHECK-NEXT: [[CALL1:%.*]] = call { ptr, i64 } @bar(i64 0)324; CHECK-NEXT: [[VAL11:%.*]] = extractvalue { ptr, i64 } [[CALL1]], 0325; CHECK-NEXT: [[VAL12:%.*]] = extractvalue { ptr, i64 } [[CALL1]], 1326; CHECK-NEXT: br label %[[EXIT:.*]]327; CHECK: [[BBB2]]:328; CHECK-NEXT: br label %[[EXIT]]329; CHECK: [[EXIT]]:330; CHECK-NEXT: [[VAL1:%.*]] = phi ptr [ [[VAL11]], %[[BBB1]] ], [ undef, %[[BBB2]] ]331; CHECK-NEXT: [[VAL2:%.*]] = phi i64 [ [[VAL12]], %[[BBB1]] ], [ 1, %[[BBB2]] ]332; CHECK-NEXT: [[TMP:%.*]] = insertvalue { ptr, i64 } poison, ptr [[VAL1]], 0333; CHECK-NEXT: [[RES:%.*]] = insertvalue { ptr, i64 } [[TMP]], i64 [[VAL2]], 1334; CHECK-NEXT: ret { ptr, i64 } [[RES]]335;336 br i1 %cond1, label %bbb1, label %bbb2337 338bbb1:339 %call1 = call {ptr, i64} @bar(i64 0)340 %val11 = extractvalue { ptr, i64 } %call1, 0341 %val12 = extractvalue { ptr, i64 } %call1, 1342 br label %exit343 344bbb2:345 br label %exit346 347exit:348 %val1 = phi ptr [%val11, %bbb1], [undef, %bbb2]349 %val2 = phi i64 [%val12, %bbb1], [1, %bbb2]350 %tmp = insertvalue { ptr, i64 } poison, ptr %val1, 0351 %res = insertvalue { ptr, i64 } %tmp, i64 %val2, 1352 ret {ptr, i64} %res353}354