forked from OSchip/llvm-project
Revert "[InstCombine] Fold PHIs with equal incoming pointers"
This reverts commit a2f6ae9abf
.
It is reverted due to clang-cmake-armv7-selfhost buildbot failure.
This commit is contained in:
parent
8715ffdf1a
commit
4c9d0da838
|
@ -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);
|
||||
|
|
|
@ -1122,68 +1122,6 @@ Instruction *InstCombiner::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) {
|
|||
return replaceInstUsesWith(FirstPhi, Undef);
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::FoldPHIWithEqualPointers(PHINode &PN) {
|
||||
auto *PhiTy = dyn_cast<PointerType>(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<PointerType>(Base->getType());
|
||||
if (BaseTy->getAddressSpace() != PhiTy->getAddressSpace())
|
||||
return nullptr;
|
||||
|
||||
for (Use &Incoming : PN.incoming_values()) {
|
||||
if (!isa<Instruction>(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<Instruction>(Base)) {
|
||||
if (isa<PHINode>(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<Instruction>(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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue