608 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=instcombine,verify -S < %s | FileCheck %s --check-prefixes=ALL,INSTCOMBINE3 4; Make sure GVN won't undo the transformation:5; RUN: opt -passes=instcombine,gvn -S < %s | FileCheck %s --check-prefixes=ALL,INSTCOMBINEGVN6 7declare ptr @get_ptr.i8()8declare ptr @get_ptr.i32()9declare void @foo.i8(ptr)10declare void @foo.i32(ptr)11 12define i32 @test_gep_and_bitcast(i1 %cond, i1 %cond2) {13; ALL-LABEL: @test_gep_and_bitcast(14; ALL-NEXT: entry:15; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()16; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]17; ALL: bb1:18; ALL-NEXT: br label [[EXIT:%.*]]19; ALL: bb2:20; ALL-NEXT: br label [[EXIT]]21; ALL: exit:22; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 1623; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 424; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 425; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 126; ALL-NEXT: ret i32 [[RES]]27;28entry:29 %obj = call ptr @get_ptr.i8()30 br i1 %cond, label %bb1, label %bb231 32bb1:33 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 1634 %res1 = load i32, ptr %ptr135 br label %exit36 37bb2:38 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 1639 %res2 = load i32, ptr %ptr240 br label %exit41 42exit:43 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]44 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]45 store i32 1, ptr %ptr.typed46 %res.load = load i32, ptr %ptr.typed47 %res = select i1 %cond2, i32 %res.phi, i32 %res.load48 ret i32 %res49}50 51define i32 @test_gep_and_bitcast_arg(ptr %obj, i1 %cond, i1 %cond2) {52; ALL-LABEL: @test_gep_and_bitcast_arg(53; ALL-NEXT: entry:54; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]55; ALL: bb1:56; ALL-NEXT: br label [[EXIT:%.*]]57; ALL: bb2:58; ALL-NEXT: br label [[EXIT]]59; ALL: exit:60; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ:%.*]], i64 1661; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 462; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 463; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 164; ALL-NEXT: ret i32 [[RES]]65;66entry:67 br i1 %cond, label %bb1, label %bb268 69bb1:70 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 1671 %res1 = load i32, ptr %ptr172 br label %exit73 74bb2:75 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 1676 %res2 = load i32, ptr %ptr277 br label %exit78 79exit:80 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]81 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]82 store i32 1, ptr %ptr.typed83 %res.load = load i32, ptr %ptr.typed84 %res = select i1 %cond2, i32 %res.phi, i32 %res.load85 ret i32 %res86}87 88define i32 @test_gep_and_bitcast_phi(i1 %cond, i1 %cond2, i1 %cond3) {89; ALL-LABEL: @test_gep_and_bitcast_phi(90; ALL-NEXT: entry:91; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]92; ALL: bb1:93; ALL-NEXT: [[OBJ1:%.*]] = call ptr @get_ptr.i8()94; ALL-NEXT: br label [[MERGE:%.*]]95; ALL: bb2:96; ALL-NEXT: [[OBJ2_TYPED:%.*]] = call ptr @get_ptr.i32()97; ALL-NEXT: br label [[MERGE]]98; ALL: merge:99; ALL-NEXT: [[OBJ:%.*]] = phi ptr [ [[OBJ1]], [[BB1]] ], [ [[OBJ2_TYPED]], [[BB2]] ]100; ALL-NEXT: [[ANOTHER_PHI:%.*]] = phi ptr [ [[OBJ1]], [[BB1]] ], [ null, [[BB2]] ]101; ALL-NEXT: call void @foo.i8(ptr [[ANOTHER_PHI]])102; ALL-NEXT: br i1 [[COND2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]103; ALL: bb3:104; ALL-NEXT: br label [[EXIT:%.*]]105; ALL: bb4:106; ALL-NEXT: br label [[EXIT]]107; ALL: exit:108; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16109; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4110; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4111; ALL-NEXT: [[RES:%.*]] = select i1 [[COND3:%.*]], i32 [[RES_PHI]], i32 1112; ALL-NEXT: ret i32 [[RES]]113;114entry:115 br i1 %cond, label %bb1, label %bb2116 117bb1:118 %obj1 = call ptr @get_ptr.i8()119 br label %merge120 121bb2:122 %obj2.typed = call ptr @get_ptr.i32()123 br label %merge124 125merge:126 %obj = phi ptr [ %obj1, %bb1 ], [ %obj2.typed, %bb2 ]127 %another_phi = phi ptr [ %obj1, %bb1 ], [ null, %bb2 ]128 call void @foo.i8(ptr %another_phi)129 br i1 %cond2, label %bb3, label %bb4130 131bb3:132 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16133 %res1 = load i32, ptr %ptr1134 br label %exit135 136bb4:137 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16138 %res2 = load i32, ptr %ptr2139 br label %exit140 141exit:142 %ptr.typed = phi ptr [ %ptr1, %bb3 ], [ %ptr2, %bb4 ]143 %res.phi = phi i32 [ %res1, %bb3 ], [ %res2, %bb4 ]144 store i32 1, ptr %ptr.typed145 %res.load = load i32, ptr %ptr.typed146 %res = select i1 %cond3, i32 %res.phi, i32 %res.load147 ret i32 %res148}149 150define i32 @test_gep_i32ptr(i1 %cond, i1 %cond2) {151; ALL-LABEL: @test_gep_i32ptr(152; ALL-NEXT: entry:153; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i32()154; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]155; ALL: bb1:156; ALL-NEXT: br label [[EXIT:%.*]]157; ALL: bb2:158; ALL-NEXT: br label [[EXIT]]159; ALL: exit:160; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 64161; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4162; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4163; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1164; ALL-NEXT: ret i32 [[RES]]165;166entry:167 %obj = call ptr @get_ptr.i32()168 br i1 %cond, label %bb1, label %bb2169 170bb1:171 %ptr1.typed = getelementptr inbounds i32, ptr %obj, i64 16172 %res1 = load i32, ptr %ptr1.typed173 br label %exit174 175bb2:176 %ptr2.typed = getelementptr inbounds i32, ptr %obj, i64 16177 %res2 = load i32, ptr %ptr2.typed178 br label %exit179 180exit:181 %ptr.typed = phi ptr [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ]182 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]183 store i32 1, ptr %ptr.typed184 %res.load = load i32, ptr %ptr.typed185 %res = select i1 %cond2, i32 %res.phi, i32 %res.load186 ret i32 %res187}188 189define i32 @test_gep_and_bitcast_gep_base_ptr(i1 %cond, i1 %cond2) {190; ALL-LABEL: @test_gep_and_bitcast_gep_base_ptr(191; ALL-NEXT: entry:192; ALL-NEXT: [[OBJ0:%.*]] = call ptr @get_ptr.i8()193; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]194; ALL: bb1:195; ALL-NEXT: br label [[EXIT:%.*]]196; ALL: bb2:197; ALL-NEXT: br label [[EXIT]]198; ALL: exit:199; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ0]], i64 32200; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4201; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4202; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1203; ALL-NEXT: ret i32 [[RES]]204;205entry:206 %obj0 = call ptr @get_ptr.i8()207 %obj = getelementptr inbounds i8, ptr %obj0, i64 16208 br i1 %cond, label %bb1, label %bb2209 210bb1:211 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16212 %res1 = load i32, ptr %ptr1213 br label %exit214 215bb2:216 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16217 %res2 = load i32, ptr %ptr2218 br label %exit219 220exit:221 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]222 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]223 store i32 1, ptr %ptr.typed224 %res.load = load i32, ptr %ptr.typed225 %res = select i1 %cond2, i32 %res.phi, i32 %res.load226 ret i32 %res227}228 229define i32 @test_gep_and_bitcast_same_bb(i1 %cond, i1 %cond2) {230; ALL-LABEL: @test_gep_and_bitcast_same_bb(231; ALL-NEXT: entry:232; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()233; ALL-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]234; ALL: bb2:235; ALL-NEXT: br label [[EXIT]]236; ALL: exit:237; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16238; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4239; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4240; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1241; ALL-NEXT: ret i32 [[RES]]242;243entry:244 %obj = call ptr @get_ptr.i8()245 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16246 %res1 = load i32, ptr %ptr1247 br i1 %cond, label %exit, label %bb2248 249bb2:250 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16251 %res2 = load i32, ptr %ptr2252 br label %exit253 254exit:255 %ptr.typed = phi ptr [ %ptr1, %entry ], [ %ptr2, %bb2 ]256 %res.phi = phi i32 [ %res1, %entry ], [ %res2, %bb2 ]257 store i32 1, ptr %ptr.typed258 %res.load = load i32, ptr %ptr.typed259 %res = select i1 %cond2, i32 %res.phi, i32 %res.load260 ret i32 %res261}262 263define i32 @test_gep_and_bitcast_same_bb_and_extra_use(i1 %cond, i1 %cond2) {264; INSTCOMBINE-LABEL: @test_gep_and_bitcast_same_bb_and_extra_use(265; INSTCOMBINE-NEXT: entry:266; INSTCOMBINE-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()267; INSTCOMBINE-NEXT: [[PTR1:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16268; INSTCOMBINE-NEXT: call void @foo.i32(ptr nonnull [[PTR1]])269; INSTCOMBINE-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]270; INSTCOMBINE: bb2:271; INSTCOMBINE-NEXT: [[PTR2:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16272; INSTCOMBINE-NEXT: br label [[EXIT]]273; INSTCOMBINE: exit:274; INSTCOMBINE-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[ENTRY:%.*]] ], [ [[PTR2]], [[BB2]] ]275; INSTCOMBINE-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4276; INSTCOMBINE-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4277; INSTCOMBINE-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1278; INSTCOMBINE-NEXT: ret i32 [[RES]]279;280; INSTCOMBINEGVN-LABEL: @test_gep_and_bitcast_same_bb_and_extra_use(281; INSTCOMBINEGVN-NEXT: entry:282; INSTCOMBINEGVN-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()283; INSTCOMBINEGVN-NEXT: [[PTR1:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16284; INSTCOMBINEGVN-NEXT: call void @foo.i32(ptr nonnull [[PTR1]])285; INSTCOMBINEGVN-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]286; INSTCOMBINEGVN: bb2:287; INSTCOMBINEGVN-NEXT: br label [[EXIT]]288; INSTCOMBINEGVN: exit:289; INSTCOMBINEGVN-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR1]], align 4290; INSTCOMBINEGVN-NEXT: store i32 1, ptr [[PTR1]], align 4291; INSTCOMBINEGVN-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1292; INSTCOMBINEGVN-NEXT: ret i32 [[RES]]293;294entry:295 %obj = call ptr @get_ptr.i8()296 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16297 call void @foo.i32(ptr %ptr1)298 %res1 = load i32, ptr %ptr1299 br i1 %cond, label %exit, label %bb2300 301bb2:302 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16303 %res2 = load i32, ptr %ptr2304 br label %exit305 306exit:307 %ptr.typed = phi ptr [ %ptr1, %entry ], [ %ptr2, %bb2 ]308 %res.phi = phi i32 [ %res1, %entry ], [ %res2, %bb2 ]309 store i32 1, ptr %ptr.typed310 %res.load = load i32, ptr %ptr.typed311 %res = select i1 %cond2, i32 %res.phi, i32 %res.load312 ret i32 %res313}314 315define i8 @test_gep(i1 %cond, i1 %cond2) {316; ALL-LABEL: @test_gep(317; ALL-NEXT: entry:318; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()319; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]320; ALL: bb1:321; ALL-NEXT: br label [[EXIT:%.*]]322; ALL: bb2:323; ALL-NEXT: br label [[EXIT]]324; ALL: exit:325; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16326; ALL-NEXT: [[RES_PHI:%.*]] = load i8, ptr [[PTR_TYPED]], align 1327; ALL-NEXT: store i8 1, ptr [[PTR_TYPED]], align 1328; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1329; ALL-NEXT: ret i8 [[RES]]330;331entry:332 %obj = call ptr @get_ptr.i8()333 br i1 %cond, label %bb1, label %bb2334 335bb1:336 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16337 %res1 = load i8, ptr %ptr1338 br label %exit339 340bb2:341 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16342 %res2 = load i8, ptr %ptr2343 br label %exit344 345exit:346 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]347 %res.phi = phi i8 [ %res1, %bb1 ], [ %res2, %bb2 ]348 store i8 1, ptr %ptr.typed349 %res.load = load i8, ptr %ptr.typed350 %res = select i1 %cond2, i8 %res.phi, i8 %res.load351 ret i8 %res352}353 354define i32 @test_extra_uses(i1 %cond, i1 %cond2) {355; ALL-LABEL: @test_extra_uses(356; ALL-NEXT: entry:357; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()358; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]359; ALL: bb1:360; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16361; ALL-NEXT: [[RES1:%.*]] = load i32, ptr [[PTR1]], align 4362; ALL-NEXT: call void @foo.i32(ptr nonnull [[PTR1]])363; ALL-NEXT: br label [[EXIT:%.*]]364; ALL: bb2:365; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16366; ALL-NEXT: [[RES2:%.*]] = load i32, ptr [[PTR2]], align 4367; ALL-NEXT: call void @foo.i32(ptr nonnull [[PTR2]])368; ALL-NEXT: br label [[EXIT]]369; ALL: exit:370; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]371; ALL-NEXT: [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]372; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4373; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1374; ALL-NEXT: ret i32 [[RES]]375;376entry:377 %obj = call ptr @get_ptr.i8()378 br i1 %cond, label %bb1, label %bb2379 380bb1:381 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16382 %res1 = load i32, ptr %ptr1383 call void @foo.i32(ptr %ptr1)384 br label %exit385 386bb2:387 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16388 %res2 = load i32, ptr %ptr2389 call void @foo.i32(ptr %ptr2)390 br label %exit391 392exit:393 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]394 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]395 store i32 1, ptr %ptr.typed396 %res.load = load i32, ptr %ptr.typed397 %res = select i1 %cond2, i32 %res.phi, i32 %res.load398 ret i32 %res399}400 401define i32 @test_extra_uses_non_inbounds(i1 %cond, i1 %cond2) {402; ALL-LABEL: @test_extra_uses_non_inbounds(403; ALL-NEXT: entry:404; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()405; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]406; ALL: bb1:407; ALL-NEXT: [[PTR1:%.*]] = getelementptr i8, ptr [[OBJ]], i64 16408; ALL-NEXT: [[RES1:%.*]] = load i32, ptr [[PTR1]], align 4409; ALL-NEXT: call void @foo.i32(ptr nonnull [[PTR1]])410; ALL-NEXT: br label [[EXIT:%.*]]411; ALL: bb2:412; ALL-NEXT: [[PTR2:%.*]] = getelementptr i8, ptr [[OBJ]], i64 16413; ALL-NEXT: [[RES2:%.*]] = load i32, ptr [[PTR2]], align 4414; ALL-NEXT: call void @foo.i32(ptr nonnull [[PTR2]])415; ALL-NEXT: br label [[EXIT]]416; ALL: exit:417; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]418; ALL-NEXT: [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]419; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4420; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1421; ALL-NEXT: ret i32 [[RES]]422;423entry:424 %obj = call ptr @get_ptr.i8()425 br i1 %cond, label %bb1, label %bb2426 427bb1:428 %ptr1 = getelementptr i8, ptr %obj, i64 16429 %res1 = load i32, ptr %ptr1430 call void @foo.i32(ptr %ptr1)431 br label %exit432 433bb2:434 %ptr2 = getelementptr i8, ptr %obj, i64 16435 %res2 = load i32, ptr %ptr2436 call void @foo.i32(ptr %ptr2)437 br label %exit438 439exit:440 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]441 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]442 store i32 1, ptr %ptr.typed443 %res.load = load i32, ptr %ptr.typed444 %res = select i1 %cond2, i32 %res.phi, i32 %res.load445 ret i32 %res446}447 448define i32 @test_extra_uses_multiple_geps(i1 %cond, i1 %cond2) {449; ALL-LABEL: @test_extra_uses_multiple_geps(450; ALL-NEXT: entry:451; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()452; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]453; ALL: bb1:454; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16455; ALL-NEXT: [[RES1:%.*]] = load i32, ptr [[PTR1]], align 4456; ALL-NEXT: call void @foo.i32(ptr nonnull [[PTR1]])457; ALL-NEXT: br label [[EXIT:%.*]]458; ALL: bb2:459; ALL-NEXT: [[PTR2_1:%.*]] = getelementptr i8, ptr [[OBJ]], i64 16460; ALL-NEXT: [[RES2:%.*]] = load i32, ptr [[PTR2_1]], align 4461; ALL-NEXT: call void @foo.i32(ptr nonnull [[PTR2_1]])462; ALL-NEXT: br label [[EXIT]]463; ALL: exit:464; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2_1]], [[BB2]] ]465; ALL-NEXT: [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]466; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4467; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1468; ALL-NEXT: ret i32 [[RES]]469;470entry:471 %obj = call ptr @get_ptr.i8()472 br i1 %cond, label %bb1, label %bb2473 474bb1:475 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16476 %res1 = load i32, ptr %ptr1477 call void @foo.i32(ptr %ptr1)478 br label %exit479 480bb2:481 %ptr2.0 = getelementptr i8, ptr %obj, i64 8482 %ptr2.1 = getelementptr inbounds i8, ptr %ptr2.0, i64 8483 %res2 = load i32, ptr %ptr2.1484 call void @foo.i32(ptr %ptr2.1)485 br label %exit486 487exit:488 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2.1, %bb2 ]489 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]490 store i32 1, ptr %ptr.typed491 %res.load = load i32, ptr %ptr.typed492 %res = select i1 %cond2, i32 %res.phi, i32 %res.load493 ret i32 %res494}495 496define i8 @test_gep_extra_uses(i1 %cond, i1 %cond2) {497; ALL-LABEL: @test_gep_extra_uses(498; ALL-NEXT: entry:499; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()500; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]501; ALL: bb1:502; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16503; ALL-NEXT: [[RES1:%.*]] = load i8, ptr [[PTR1]], align 1504; ALL-NEXT: call void @foo.i8(ptr nonnull [[PTR1]])505; ALL-NEXT: br label [[EXIT:%.*]]506; ALL: bb2:507; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16508; ALL-NEXT: [[RES2:%.*]] = load i8, ptr [[PTR2]], align 1509; ALL-NEXT: call void @foo.i8(ptr nonnull [[PTR2]])510; ALL-NEXT: br label [[EXIT]]511; ALL: exit:512; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]513; ALL-NEXT: [[RES_PHI:%.*]] = phi i8 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]514; ALL-NEXT: store i8 1, ptr [[PTR_TYPED]], align 1515; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1516; ALL-NEXT: ret i8 [[RES]]517;518entry:519 %obj = call ptr @get_ptr.i8()520 br i1 %cond, label %bb1, label %bb2521 522bb1:523 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16524 %res1 = load i8, ptr %ptr1525 call void @foo.i8(ptr %ptr1)526 br label %exit527 528bb2:529 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16530 %res2 = load i8, ptr %ptr2531 call void @foo.i8(ptr %ptr2)532 br label %exit533 534exit:535 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]536 %res.phi = phi i8 [ %res1, %bb1 ], [ %res2, %bb2 ]537 store i8 1, ptr %ptr.typed538 %res.load = load i8, ptr %ptr.typed539 %res = select i1 %cond2, i8 %res.phi, i8 %res.load540 ret i8 %res541}542 543; `swifterror` addresses are restricted to load and stores and call arguments.544declare void @takeAddress(ptr swifterror)545 546define ptr @test_dont_optimize_swifterror(i1 %cond, i1 %cond2, ptr %ptr) {547; INSTCOMBINE-LABEL: @test_dont_optimize_swifterror(548; INSTCOMBINE-NEXT: entry:549; INSTCOMBINE-NEXT: [[OBJ:%.*]] = alloca swifterror ptr, align 8550; INSTCOMBINE-NEXT: [[OBJ2:%.*]] = alloca swifterror ptr, align 8551; INSTCOMBINE-NEXT: call void @takeAddress(ptr nonnull swifterror [[OBJ]])552; INSTCOMBINE-NEXT: call void @takeAddress(ptr nonnull swifterror [[OBJ2]])553; INSTCOMBINE-NEXT: store ptr [[PTR:%.*]], ptr [[OBJ]], align 8554; INSTCOMBINE-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]555; INSTCOMBINE: bb1:556; INSTCOMBINE-NEXT: [[RES1:%.*]] = load ptr, ptr [[OBJ]], align 8557; INSTCOMBINE-NEXT: br label [[EXIT:%.*]]558; INSTCOMBINE: bb2:559; INSTCOMBINE-NEXT: [[RES2:%.*]] = load ptr, ptr [[OBJ2]], align 8560; INSTCOMBINE-NEXT: br label [[EXIT]]561; INSTCOMBINE: exit:562; INSTCOMBINE-NEXT: [[RES_PHI:%.*]] = phi ptr [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]563; INSTCOMBINE-NEXT: store ptr null, ptr [[OBJ]], align 8564; INSTCOMBINE-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], ptr [[RES_PHI]], ptr null565; INSTCOMBINE-NEXT: ret ptr [[RES]]566;567; INSTCOMBINEGVN-LABEL: @test_dont_optimize_swifterror(568; INSTCOMBINEGVN-NEXT: entry:569; INSTCOMBINEGVN-NEXT: [[OBJ:%.*]] = alloca swifterror ptr, align 8570; INSTCOMBINEGVN-NEXT: [[OBJ2:%.*]] = alloca swifterror ptr, align 8571; INSTCOMBINEGVN-NEXT: call void @takeAddress(ptr nonnull swifterror [[OBJ]])572; INSTCOMBINEGVN-NEXT: call void @takeAddress(ptr nonnull swifterror [[OBJ2]])573; INSTCOMBINEGVN-NEXT: store ptr [[PTR:%.*]], ptr [[OBJ]], align 8574; INSTCOMBINEGVN-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]575; INSTCOMBINEGVN: bb1:576; INSTCOMBINEGVN-NEXT: br label [[EXIT:%.*]]577; INSTCOMBINEGVN: bb2:578; INSTCOMBINEGVN-NEXT: [[RES2:%.*]] = load ptr, ptr [[OBJ2]], align 8579; INSTCOMBINEGVN-NEXT: br label [[EXIT]]580; INSTCOMBINEGVN: exit:581; INSTCOMBINEGVN-NEXT: [[RES_PHI:%.*]] = phi ptr [ [[PTR]], [[BB1]] ], [ [[RES2]], [[BB2]] ]582; INSTCOMBINEGVN-NEXT: store ptr null, ptr [[OBJ]], align 8583; INSTCOMBINEGVN-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], ptr [[RES_PHI]], ptr null584; INSTCOMBINEGVN-NEXT: ret ptr [[RES]]585;586entry:587 %obj = alloca swifterror ptr, align 8588 %obj2 = alloca swifterror ptr, align 8589 call void @takeAddress(ptr swifterror %obj)590 call void @takeAddress(ptr swifterror %obj2)591 store ptr %ptr, ptr %obj, align 8592 br i1 %cond, label %bb1, label %bb2593 594bb1: ; preds = %entry595 %res1 = load ptr, ptr %obj, align 8596 br label %exit597 598bb2: ; preds = %entry599 %res2 = load ptr, ptr %obj2, align 8600 br label %exit601 602exit: ; preds = %bb2, %bb1603 %res.phi = phi ptr [ %res1, %bb1 ], [ %res2, %bb2 ]604 store ptr null, ptr %obj, align 8605 %res = select i1 %cond2, ptr %res.phi, ptr null606 ret ptr %res607}608