From 4c9d0da8382f176a2fb7b97298932a53d22e8627 Mon Sep 17 00:00:00 2001 From: Daniil Suchkov Date: Thu, 14 Nov 2019 17:42:01 +0700 Subject: [PATCH] Revert "[InstCombine] Fold PHIs with equal incoming pointers" This reverts commit a2f6ae9abffcba260c22bb235879f0576bf3b783. It is reverted due to clang-cmake-armv7-selfhost buildbot failure. --- .../InstCombine/InstCombineInternal.h | 5 - .../Transforms/InstCombine/InstCombinePHI.cpp | 65 --- .../phi-equal-incoming-pointers.ll | 536 +++++------------- 3 files changed, 136 insertions(+), 470 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h index 52aeb787aaf9..524f9313d8c4 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -895,11 +895,6 @@ private: /// insert a new pointer typed PHI and replace the original one. Instruction *FoldIntegerTypedPHI(PHINode &PN); - /// If all incoming values of a pointer typed PHI are pointers with the same - /// base and offset, replace the PHI and all incoming values with one - /// definition of such pointer. - Instruction *FoldPHIWithEqualPointers(PHINode &PN); - /// Helper function for FoldPHIArgXIntoPHI() to set debug location for the /// folded operation. void PHIArgMergedDebugLoc(Instruction *Inst, PHINode &PN); diff --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp index d1035414560b..e0376b7582f3 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -1122,68 +1122,6 @@ Instruction *InstCombiner::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) { return replaceInstUsesWith(FirstPhi, Undef); } -Instruction *InstCombiner::FoldPHIWithEqualPointers(PHINode &PN) { - auto *PhiTy = dyn_cast(PN.getType()); - if (!PhiTy) - return nullptr; - - // Make sure all incoming pointers have the same base pointers and offsets. - // Also, make sure no addrspacecasts involved. - // Note: only inbounds GEPs are supported! - const DataLayout &DL = PN.getModule()->getDataLayout(); - Value *FirstValue = PN.getIncomingValue(0); - int64_t Offset; - Value *Base = GetPointerBaseWithConstantOffset( - FirstValue, Offset, DL, /* AllowNonInbounds */ false); - - auto *BaseTy = cast(Base->getType()); - if (BaseTy->getAddressSpace() != PhiTy->getAddressSpace()) - return nullptr; - - for (Use &Incoming : PN.incoming_values()) { - if (!isa(Incoming)) - return nullptr; - int64_t CurrentOffset; - Value *CurrentBase = GetPointerBaseWithConstantOffset( - Incoming, CurrentOffset, DL, /* AllowNonInbounds */ false); - if (CurrentBase != Base || CurrentOffset != Offset) - return nullptr; - } - - Instruction *InsertPt = nullptr; - if (auto *BaseInst = dyn_cast(Base)) { - if (isa(BaseInst)) { - BasicBlock *InsertBB = BaseInst->getParent(); - BasicBlock::iterator InsertPtIter = InsertBB->getFirstInsertionPt(); - // Make sure the insertion point exists. At the moment the only reason why - // insertion point may not exist is EHPad being a terminator. This check - // is a bit more future-proof than just `if (!TI->isEHPad())`. - if (InsertPtIter != InsertBB->end()) - InsertPt = &*InsertPtIter; - } else - InsertPt = BaseInst->getNextNode(); - } else - InsertPt = &*PN.getFunction()->getEntryBlock().getFirstInsertionPt(); - - if (!InsertPt) - return nullptr; - - Builder.SetInsertPoint(InsertPt); - Type *I8PtrTy = Builder.getInt8PtrTy(PhiTy->getAddressSpace()); - Value *BaseI8Ptr = Builder.CreateBitCast(Base, I8PtrTy); - Value *GEP = Builder.CreateConstInBoundsGEP1_64(BaseI8Ptr, Offset); - Value *GEPTyped = Builder.CreateBitCast(GEP, PhiTy); - - for (Use &Incoming : PN.incoming_values()) { - auto *IncomingInst = cast(Incoming); - // If we haven't already replaced this instruction. - if (IncomingInst != GEPTyped) - replaceInstUsesWith(*IncomingInst, GEPTyped); - } - - return replaceInstUsesWith(PN, GEPTyped); -} - // PHINode simplification // Instruction *InstCombiner::visitPHINode(PHINode &PN) { @@ -1205,9 +1143,6 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) { if (Instruction *Result = FoldPHIArgOpIntoPHI(PN)) return Result; - if (Instruction *Result = FoldPHIWithEqualPointers(PN)) - return Result; - // If this is a trivial cycle in the PHI node graph, remove it. Basically, if // this PHI only has a single use (a PHI), and if that PHI only has one use (a // PHI)... break the cycle. diff --git a/llvm/test/Transforms/InstCombine/phi-equal-incoming-pointers.ll b/llvm/test/Transforms/InstCombine/phi-equal-incoming-pointers.ll index 4404126c33a4..882df7b37229 100644 --- a/llvm/test/Transforms/InstCombine/phi-equal-incoming-pointers.ll +++ b/llvm/test/Transforms/InstCombine/phi-equal-incoming-pointers.ll @@ -13,16 +13,20 @@ define i32 @test_gep_and_bitcast(i1 %cond, i1 %cond2) { ; ALL-LABEL: @test_gep_and_bitcast( ; ALL-NEXT: entry: ; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 -; ALL-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; ALL: bb1: +; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* ; ALL-NEXT: br label [[EXIT:%.*]] ; ALL: bb2: +; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32* ; ALL-NEXT: br label [[EXIT]] ; ALL: exit: -; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: store i32 1, i32* [[TMP1]], align 4 +; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] +; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] +; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4 +; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4 ; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 ; ALL-NEXT: ret i32 [[RES]] ; @@ -51,122 +55,23 @@ exit: ret i32 %res } -define i32 @test_gep_and_bitcast_2_same_incoming_instructions(i1 %cond, i1 %cond2, i1 %cond3) { -; ALL-LABEL: @test_gep_and_bitcast_2_same_incoming_instructions( -; ALL-NEXT: entry: -; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 -; ALL-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* -; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] -; ALL: bb1: -; ALL-NEXT: [[RES1:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: br label [[EXIT:%.*]] -; ALL: bb2: -; ALL-NEXT: [[RES2:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: br i1 [[COND3:%.*]], label [[EXIT]], label [[BB3:%.*]] -; ALL: bb3: -; ALL-NEXT: br label [[EXIT]] -; ALL: exit: -; ALL-NEXT: [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ], [ [[RES2]], [[BB3]] ] -; ALL-NEXT: store i32 1, i32* [[TMP1]], align 4 -; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 -; ALL-NEXT: ret i32 [[RES]] -; -entry: - %obj = call i8* @get_ptr.i8() - br i1 %cond, label %bb1, label %bb2 - -bb1: - %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16 - %ptr1.typed = bitcast i8* %ptr1 to i32* - %res1 = load i32, i32* %ptr1.typed - br label %exit - -bb2: - %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16 - %ptr2.typed = bitcast i8* %ptr2 to i32* - %res2 = load i32, i32* %ptr2.typed - br i1 %cond3, label %exit, label %bb3 - -bb3: - br label %exit - -exit: - %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ], [ %ptr2.typed, %bb3 ] - %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ], [ %res2, %bb3 ] - store i32 1, i32* %ptr.typed - %res.load = load i32, i32* %ptr.typed - %res = select i1 %cond2, i32 %res.phi, i32 %res.load - ret i32 %res -} - -define i32 @test_gep_and_bitcast_3_same_incoming_instructions(i1 %cond, i1 %cond2, i1 %cond3, i1 %cond4) { -; ALL-LABEL: @test_gep_and_bitcast_3_same_incoming_instructions( -; ALL-NEXT: entry: -; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 -; ALL-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* -; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] -; ALL: bb1: -; ALL-NEXT: [[RES1:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: br label [[EXIT:%.*]] -; ALL: bb2: -; ALL-NEXT: [[RES2:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: br i1 [[COND3:%.*]], label [[EXIT]], label [[BB3:%.*]] -; ALL: bb3: -; ALL-NEXT: br i1 [[COND4:%.*]], label [[EXIT]], label [[BB4:%.*]] -; ALL: bb4: -; ALL-NEXT: br label [[EXIT]] -; ALL: exit: -; ALL-NEXT: [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ], [ [[RES2]], [[BB3]] ], [ [[RES2]], [[BB4]] ] -; ALL-NEXT: store i32 1, i32* [[TMP1]], align 4 -; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 -; ALL-NEXT: ret i32 [[RES]] -; -entry: - %obj = call i8* @get_ptr.i8() - br i1 %cond, label %bb1, label %bb2 - -bb1: - %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16 - %ptr1.typed = bitcast i8* %ptr1 to i32* - %res1 = load i32, i32* %ptr1.typed - br label %exit - -bb2: - %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16 - %ptr2.typed = bitcast i8* %ptr2 to i32* - %res2 = load i32, i32* %ptr2.typed - br i1 %cond3, label %exit, label %bb3 - -bb3: - br i1 %cond4, label %exit, label %bb4 - -bb4: - br label %exit - -exit: - %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ], [ %ptr2.typed, %bb3 ], [ %ptr2.typed, %bb4 ] - %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ], [ %res2, %bb3 ], [ %res2, %bb4 ] - store i32 1, i32* %ptr.typed - %res.load = load i32, i32* %ptr.typed - %res = select i1 %cond2, i32 %res.phi, i32 %res.load - ret i32 %res -} - define i32 @test_gep_and_bitcast_arg(i8* %obj, i1 %cond, i1 %cond2) { ; ALL-LABEL: @test_gep_and_bitcast_arg( ; ALL-NEXT: entry: -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[OBJ:%.*]], i64 16 -; ALL-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; ALL: bb1: +; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ:%.*]], i64 16 +; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* ; ALL-NEXT: br label [[EXIT:%.*]] ; ALL: bb2: +; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32* ; ALL-NEXT: br label [[EXIT]] ; ALL: exit: -; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: store i32 1, i32* [[TMP1]], align 4 +; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] +; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] +; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4 +; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4 ; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 ; ALL-NEXT: ret i32 [[RES]] ; @@ -208,17 +113,21 @@ define i32 @test_gep_and_bitcast_phi(i1 %cond, i1 %cond2, i1 %cond3) { ; ALL: merge: ; ALL-NEXT: [[OBJ:%.*]] = phi i8* [ [[OBJ1]], [[BB1]] ], [ [[OBJ2]], [[BB2]] ] ; ALL-NEXT: [[ANOTHER_PHI:%.*]] = phi i8* [ [[OBJ1]], [[BB1]] ], [ null, [[BB2]] ] -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 -; ALL-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* ; ALL-NEXT: call void @foo.i8(i8* [[ANOTHER_PHI]]) ; ALL-NEXT: br i1 [[COND2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]] ; ALL: bb3: +; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* ; ALL-NEXT: br label [[EXIT:%.*]] ; ALL: bb4: +; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32* ; ALL-NEXT: br label [[EXIT]] ; ALL: exit: -; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: store i32 1, i32* [[TMP1]], align 4 +; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB3]] ], [ [[PTR2_TYPED]], [[BB4]] ] +; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB3]] ], [ [[PTR2_TYPED]], [[BB4]] ] +; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4 +; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4 ; ALL-NEXT: [[RES:%.*]] = select i1 [[COND3:%.*]], i32 [[RES_PHI]], i32 1 ; ALL-NEXT: ret i32 [[RES]] ; @@ -265,15 +174,18 @@ define i32 @test_gep_i32ptr(i1 %cond, i1 %cond2) { ; ALL-LABEL: @test_gep_i32ptr( ; ALL-NEXT: entry: ; ALL-NEXT: [[OBJ:%.*]] = call i32* @get_ptr.i32() -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[OBJ]], i64 16 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; ALL: bb1: +; ALL-NEXT: [[PTR1_TYPED:%.*]] = getelementptr inbounds i32, i32* [[OBJ]], i64 16 ; ALL-NEXT: br label [[EXIT:%.*]] ; ALL: bb2: +; ALL-NEXT: [[PTR2_TYPED:%.*]] = getelementptr inbounds i32, i32* [[OBJ]], i64 16 ; ALL-NEXT: br label [[EXIT]] ; ALL: exit: -; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[TMP0]], align 4 -; ALL-NEXT: store i32 1, i32* [[TMP0]], align 4 +; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] +; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] +; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4 +; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4 ; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 ; ALL-NEXT: ret i32 [[RES]] ; @@ -304,16 +216,20 @@ define i32 @test_gep_and_bitcast_gep_base_ptr(i1 %cond, i1 %cond2) { ; ALL-LABEL: @test_gep_and_bitcast_gep_base_ptr( ; ALL-NEXT: entry: ; ALL-NEXT: [[OBJ0:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[OBJ0]], i64 32 -; ALL-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; ALL: bb1: +; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ0]], i64 32 +; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* ; ALL-NEXT: br label [[EXIT:%.*]] ; ALL: bb2: +; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ0]], i64 32 +; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32* ; ALL-NEXT: br label [[EXIT]] ; ALL: exit: -; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: store i32 1, i32* [[TMP1]], align 4 +; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] +; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] +; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4 +; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4 ; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 ; ALL-NEXT: ret i32 [[RES]] ; @@ -344,19 +260,37 @@ exit: } define i32 @test_gep_and_bitcast_same_bb(i1 %cond, i1 %cond2) { -; ALL-LABEL: @test_gep_and_bitcast_same_bb( -; ALL-NEXT: entry: -; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 -; ALL-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* -; ALL-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]] -; ALL: bb2: -; ALL-NEXT: br label [[EXIT]] -; ALL: exit: -; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: store i32 1, i32* [[TMP1]], align 4 -; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 -; ALL-NEXT: ret i32 [[RES]] +; INSTCOMBINE-LABEL: @test_gep_and_bitcast_same_bb( +; INSTCOMBINE-NEXT: entry: +; INSTCOMBINE-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() +; INSTCOMBINE-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; INSTCOMBINE-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* +; INSTCOMBINE-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]] +; INSTCOMBINE: bb2: +; INSTCOMBINE-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; INSTCOMBINE-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32* +; INSTCOMBINE-NEXT: br label [[EXIT]] +; INSTCOMBINE: exit: +; INSTCOMBINE-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[ENTRY:%.*]] ], [ [[PTR2_TYPED]], [[BB2]] ] +; INSTCOMBINE-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[ENTRY]] ], [ [[PTR2_TYPED]], [[BB2]] ] +; INSTCOMBINE-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4 +; INSTCOMBINE-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4 +; INSTCOMBINE-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 +; INSTCOMBINE-NEXT: ret i32 [[RES]] +; +; INSTCOMBINEGVN-LABEL: @test_gep_and_bitcast_same_bb( +; INSTCOMBINEGVN-NEXT: entry: +; INSTCOMBINEGVN-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() +; INSTCOMBINEGVN-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; INSTCOMBINEGVN-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* +; INSTCOMBINEGVN-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]] +; INSTCOMBINEGVN: bb2: +; INSTCOMBINEGVN-NEXT: br label [[EXIT]] +; INSTCOMBINEGVN: exit: +; INSTCOMBINEGVN-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[PTR1_TYPED]], align 4 +; INSTCOMBINEGVN-NEXT: store i32 1, i32* [[PTR1_TYPED]], align 4 +; INSTCOMBINEGVN-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 +; INSTCOMBINEGVN-NEXT: ret i32 [[RES]] ; entry: %obj = call i8* @get_ptr.i8() @@ -381,20 +315,39 @@ exit: } define i32 @test_gep_and_bitcast_same_bb_and_extra_use(i1 %cond, i1 %cond2) { -; ALL-LABEL: @test_gep_and_bitcast_same_bb_and_extra_use( -; ALL-NEXT: entry: -; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 -; ALL-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* -; ALL-NEXT: call void @foo.i32(i32* nonnull [[TMP1]]) -; ALL-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]] -; ALL: bb2: -; ALL-NEXT: br label [[EXIT]] -; ALL: exit: -; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: store i32 1, i32* [[TMP1]], align 4 -; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 -; ALL-NEXT: ret i32 [[RES]] +; INSTCOMBINE-LABEL: @test_gep_and_bitcast_same_bb_and_extra_use( +; INSTCOMBINE-NEXT: entry: +; INSTCOMBINE-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() +; INSTCOMBINE-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; INSTCOMBINE-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* +; INSTCOMBINE-NEXT: call void @foo.i32(i32* nonnull [[PTR1_TYPED]]) +; INSTCOMBINE-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]] +; INSTCOMBINE: bb2: +; INSTCOMBINE-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; INSTCOMBINE-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32* +; INSTCOMBINE-NEXT: br label [[EXIT]] +; INSTCOMBINE: exit: +; INSTCOMBINE-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[ENTRY:%.*]] ], [ [[PTR2_TYPED]], [[BB2]] ] +; INSTCOMBINE-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[ENTRY]] ], [ [[PTR2_TYPED]], [[BB2]] ] +; INSTCOMBINE-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4 +; INSTCOMBINE-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4 +; INSTCOMBINE-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 +; INSTCOMBINE-NEXT: ret i32 [[RES]] +; +; INSTCOMBINEGVN-LABEL: @test_gep_and_bitcast_same_bb_and_extra_use( +; INSTCOMBINEGVN-NEXT: entry: +; INSTCOMBINEGVN-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() +; INSTCOMBINEGVN-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; INSTCOMBINEGVN-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* +; INSTCOMBINEGVN-NEXT: call void @foo.i32(i32* nonnull [[PTR1_TYPED]]) +; INSTCOMBINEGVN-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]] +; INSTCOMBINEGVN: bb2: +; INSTCOMBINEGVN-NEXT: br label [[EXIT]] +; INSTCOMBINEGVN: exit: +; INSTCOMBINEGVN-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[PTR1_TYPED]], align 4 +; INSTCOMBINEGVN-NEXT: store i32 1, i32* [[PTR1_TYPED]], align 4 +; INSTCOMBINEGVN-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 +; INSTCOMBINEGVN-NEXT: ret i32 [[RES]] ; entry: %obj = call i8* @get_ptr.i8() @@ -423,15 +376,18 @@ define i8 @test_gep(i1 %cond, i1 %cond2) { ; ALL-LABEL: @test_gep( ; ALL-NEXT: entry: ; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; ALL: bb1: +; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 ; ALL-NEXT: br label [[EXIT:%.*]] ; ALL: bb2: +; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 ; ALL-NEXT: br label [[EXIT]] ; ALL: exit: -; ALL-NEXT: [[RES_PHI:%.*]] = load i8, i8* [[TMP0]], align 1 -; ALL-NEXT: store i8 1, i8* [[TMP0]], align 1 +; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i8* [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ] +; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i8* [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ] +; ALL-NEXT: [[RES_PHI:%.*]] = load i8, i8* [[RES_PHI_IN]], align 1 +; ALL-NEXT: store i8 1, i8* [[PTR_TYPED]], align 1 ; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1 ; ALL-NEXT: ret i8 [[RES]] ; @@ -462,20 +418,23 @@ define i32 @test_extra_uses(i1 %cond, i1 %cond2) { ; ALL-LABEL: @test_extra_uses( ; ALL-NEXT: entry: ; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 -; ALL-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; ALL: bb1: -; ALL-NEXT: [[RES1:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: call void @foo.i32(i32* nonnull [[TMP1]]) +; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* +; ALL-NEXT: [[RES1:%.*]] = load i32, i32* [[PTR1_TYPED]], align 4 +; ALL-NEXT: call void @foo.i32(i32* nonnull [[PTR1_TYPED]]) ; ALL-NEXT: br label [[EXIT:%.*]] ; ALL: bb2: -; ALL-NEXT: [[RES2:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: call void @foo.i32(i32* nonnull [[TMP1]]) +; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32* +; ALL-NEXT: [[RES2:%.*]] = load i32, i32* [[PTR2_TYPED]], align 4 +; ALL-NEXT: call void @foo.i32(i32* nonnull [[PTR2_TYPED]]) ; ALL-NEXT: br label [[EXIT]] ; ALL: exit: +; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] ; ALL-NEXT: [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ] -; ALL-NEXT: store i32 1, i32* [[TMP1]], align 4 +; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4 ; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 ; ALL-NEXT: ret i32 [[RES]] ; @@ -561,20 +520,23 @@ define i32 @test_extra_uses_multiple_geps(i1 %cond, i1 %cond2) { ; ALL-LABEL: @test_extra_uses_multiple_geps( ; ALL-NEXT: entry: ; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 -; ALL-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; ALL: bb1: -; ALL-NEXT: [[RES1:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: call void @foo.i32(i32* nonnull [[TMP1]]) +; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* +; ALL-NEXT: [[RES1:%.*]] = load i32, i32* [[PTR1_TYPED]], align 4 +; ALL-NEXT: call void @foo.i32(i32* nonnull [[PTR1_TYPED]]) ; ALL-NEXT: br label [[EXIT:%.*]] ; ALL: bb2: -; ALL-NEXT: [[RES2:%.*]] = load i32, i32* [[TMP1]], align 4 -; ALL-NEXT: call void @foo.i32(i32* nonnull [[TMP1]]) +; ALL-NEXT: [[PTR2_1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2_1]] to i32* +; ALL-NEXT: [[RES2:%.*]] = load i32, i32* [[PTR2_TYPED]], align 4 +; ALL-NEXT: call void @foo.i32(i32* nonnull [[PTR2_TYPED]]) ; ALL-NEXT: br label [[EXIT]] ; ALL: exit: +; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] ; ALL-NEXT: [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ] -; ALL-NEXT: store i32 1, i32* [[TMP1]], align 4 +; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4 ; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 ; ALL-NEXT: ret i32 [[RES]] ; @@ -610,19 +572,21 @@ define i8 @test_gep_extra_uses(i1 %cond, i1 %cond2) { ; ALL-LABEL: @test_gep_extra_uses( ; ALL-NEXT: entry: ; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; ALL: bb1: -; ALL-NEXT: [[RES1:%.*]] = load i8, i8* [[TMP0]], align 1 -; ALL-NEXT: call void @foo.i8(i8* nonnull [[TMP0]]) +; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; ALL-NEXT: [[RES1:%.*]] = load i8, i8* [[PTR1]], align 1 +; ALL-NEXT: call void @foo.i8(i8* nonnull [[PTR1]]) ; ALL-NEXT: br label [[EXIT:%.*]] ; ALL: bb2: -; ALL-NEXT: [[RES2:%.*]] = load i8, i8* [[TMP0]], align 1 -; ALL-NEXT: call void @foo.i8(i8* nonnull [[TMP0]]) +; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; ALL-NEXT: [[RES2:%.*]] = load i8, i8* [[PTR2]], align 1 +; ALL-NEXT: call void @foo.i8(i8* nonnull [[PTR2]]) ; ALL-NEXT: br label [[EXIT]] ; ALL: exit: +; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i8* [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ] ; ALL-NEXT: [[RES_PHI:%.*]] = phi i8 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ] -; ALL-NEXT: store i8 1, i8* [[TMP0]], align 1 +; ALL-NEXT: store i8 1, i8* [[PTR_TYPED]], align 1 ; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1 ; ALL-NEXT: ret i8 [[RES]] ; @@ -650,231 +614,3 @@ exit: %res = select i1 %cond2, i8 %res.phi, i8 %res.load ret i8 %res } - -define i32 @test_neg_extra_uses_inbounds_mismatch(i1 %cond, i1 %cond2) { -; ALL-LABEL: @test_neg_extra_uses_inbounds_mismatch( -; ALL-NEXT: entry: -; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] -; ALL: bb1: -; ALL-NEXT: [[PTR1:%.*]] = getelementptr i8, i8* [[OBJ]], i64 16 -; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* -; ALL-NEXT: [[RES1:%.*]] = load i32, i32* [[PTR1_TYPED]], align 4 -; ALL-NEXT: call void @foo.i32(i32* [[PTR1_TYPED]]) -; ALL-NEXT: br label [[EXIT:%.*]] -; ALL: bb2: -; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 -; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32* -; ALL-NEXT: [[RES2:%.*]] = load i32, i32* [[PTR2_TYPED]], align 4 -; ALL-NEXT: call void @foo.i32(i32* nonnull [[PTR2_TYPED]]) -; ALL-NEXT: br label [[EXIT]] -; ALL: exit: -; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] -; ALL-NEXT: [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ] -; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4 -; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 -; ALL-NEXT: ret i32 [[RES]] -; -entry: - %obj = call i8* @get_ptr.i8() - br i1 %cond, label %bb1, label %bb2 - -bb1: - %ptr1 = getelementptr i8, i8* %obj, i64 16 - %ptr1.typed = bitcast i8* %ptr1 to i32* - %res1 = load i32, i32* %ptr1.typed - call void @foo.i32(i32* %ptr1.typed) - br label %exit - -bb2: - %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16 - %ptr2.typed = bitcast i8* %ptr2 to i32* - %res2 = load i32, i32* %ptr2.typed - call void @foo.i32(i32* %ptr2.typed) - br label %exit - -exit: - %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ] - %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ] - store i32 1, i32* %ptr.typed - %res.load = load i32, i32* %ptr.typed - %res = select i1 %cond2, i32 %res.phi, i32 %res.load - ret i32 %res -} - -define i32 @test_neg_gep_and_bitcast_different_offset(i1 %cond, i1 %cond2) { -; ALL-LABEL: @test_neg_gep_and_bitcast_different_offset( -; ALL-NEXT: entry: -; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] -; ALL: bb1: -; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 -; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* -; ALL-NEXT: br label [[EXIT:%.*]] -; ALL: bb2: -; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 20 -; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32* -; ALL-NEXT: br label [[EXIT]] -; ALL: exit: -; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] -; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] -; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4 -; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4 -; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 -; ALL-NEXT: ret i32 [[RES]] -; -entry: - %obj = call i8* @get_ptr.i8() - br i1 %cond, label %bb1, label %bb2 - -bb1: - %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16 - %ptr1.typed = bitcast i8* %ptr1 to i32* - %res1 = load i32, i32* %ptr1.typed - br label %exit - -bb2: - %ptr2 = getelementptr inbounds i8, i8* %obj, i64 20 - %ptr2.typed = bitcast i8* %ptr2 to i32* - %res2 = load i32, i32* %ptr2.typed - br label %exit - -exit: - %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ] - %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ] - store i32 1, i32* %ptr.typed - %res.load = load i32, i32* %ptr.typed - %res = select i1 %cond2, i32 %res.phi, i32 %res.load - ret i32 %res -} - -define i32 @test_neg_gep_and_bitcast_different_base_ptr(i1 %cond, i1 %cond2) { -; ALL-LABEL: @test_neg_gep_and_bitcast_different_base_ptr( -; ALL-NEXT: entry: -; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: [[OBJ2:%.*]] = call i8* @get_ptr.i8() -; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] -; ALL: bb1: -; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 -; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32* -; ALL-NEXT: br label [[EXIT:%.*]] -; ALL: bb2: -; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ2]], i64 16 -; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32* -; ALL-NEXT: br label [[EXIT]] -; ALL: exit: -; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] -; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ] -; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4 -; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4 -; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 -; ALL-NEXT: ret i32 [[RES]] -; -entry: - %obj = call i8* @get_ptr.i8() - %obj2 = call i8* @get_ptr.i8() - br i1 %cond, label %bb1, label %bb2 - -bb1: - %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16 - %ptr1.typed = bitcast i8* %ptr1 to i32* - %res1 = load i32, i32* %ptr1.typed - br label %exit - -bb2: - %ptr2 = getelementptr inbounds i8, i8* %obj2, i64 16 - %ptr2.typed = bitcast i8* %ptr2 to i32* - %res2 = load i32, i32* %ptr2.typed - br label %exit - -exit: - %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ] - %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ] - store i32 1, i32* %ptr.typed - %res.load = load i32, i32* %ptr.typed - %res = select i1 %cond2, i32 %res.phi, i32 %res.load - ret i32 %res -} - -; Just to make sure we don't generate invalid IR in this case. -; There is no insertion point right after base pointer def here. -define i32 @test_neg_gep_and_bitcast_invoke(i1 %cond, i1 %cond2) personality i8 0 { -; ALL-LABEL: @test_neg_gep_and_bitcast_invoke( -; -entry: - %obj = invoke i8* @get_ptr.i8() to label %bb0 unwind label %lpad - -lpad: - %ll = landingpad { i8*, i32 } - cleanup - ret i32 0 - -bb0: - br i1 %cond, label %bb1, label %bb2 - -bb1: - %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16 - %ptr1.typed = bitcast i8* %ptr1 to i32* - %res1 = load i32, i32* %ptr1.typed - br label %exit - -bb2: - %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16 - %ptr2.typed = bitcast i8* %ptr2 to i32* - %res2 = load i32, i32* %ptr2.typed - br label %exit - -exit: - %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ] - %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ] - store i32 1, i32* %ptr.typed - %res.load = load i32, i32* %ptr.typed - %res = select i1 %cond2, i32 %res.phi, i32 %res.load - ret i32 %res -} - -; Just to make sure we don't generate invalid IR in this case. -define i32 @test_neg_gep_and_bitcast_phi_no_insert_pt(i1 %cond, i1 %cond2) personality i8 0 { -; ALL-LABEL: @test_neg_gep_and_bitcast_phi_no_insert_pt( -; -entry: - %obj1 = call i8* @get_ptr.i8() - invoke void @foo.i8(i8* null) to label %cont unwind label %catch - -cont: - %obj2.typed = call i32* @get_ptr.i32() - %obj2 = bitcast i32* %obj2.typed to i8* - invoke void @foo.i8(i8* null) to label %unreachable unwind label %catch - -catch: - ; There is no insertion point in this basic block! - %obj = phi i8* [ %obj1, %entry ], [ %obj2, %cont ] - %cs = catchswitch within none [label %doit] unwind to caller - -doit: - %cl = catchpad within %cs [] - br i1 %cond, label %bb1, label %bb2 - -bb1: - %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16 - %ptr1.typed = bitcast i8* %ptr1 to i32* - %res1 = load i32, i32* %ptr1.typed - br label %exit - -bb2: - %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16 - %ptr2.typed = bitcast i8* %ptr2 to i32* - %res2 = load i32, i32* %ptr2.typed - br label %exit - -exit: - %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ] - %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ] - store i32 1, i32* %ptr.typed - %res.load = load i32, i32* %ptr.typed - %res = select i1 %cond2, i32 %res.phi, i32 %res.load - ret i32 %res - -unreachable: - unreachable -}