aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Scalar/MergeICmps.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Scalar/MergeICmps.cpp')
-rw-r--r--llvm/lib/Transforms/Scalar/MergeICmps.cpp59
1 files changed, 35 insertions, 24 deletions
diff --git a/llvm/lib/Transforms/Scalar/MergeICmps.cpp b/llvm/lib/Transforms/Scalar/MergeICmps.cpp
index aac0deea5be3..ce01ae5b2692 100644
--- a/llvm/lib/Transforms/Scalar/MergeICmps.cpp
+++ b/llvm/lib/Transforms/Scalar/MergeICmps.cpp
@@ -144,31 +144,33 @@ BCEAtom visitICmpLoadOperand(Value *const Val, BaseIdentifier &BaseId) {
LLVM_DEBUG(dbgs() << "volatile or atomic\n");
return {};
}
- Value *const Addr = LoadI->getOperand(0);
+ Value *Addr = LoadI->getOperand(0);
if (Addr->getType()->getPointerAddressSpace() != 0) {
LLVM_DEBUG(dbgs() << "from non-zero AddressSpace\n");
return {};
}
- auto *const GEP = dyn_cast<GetElementPtrInst>(Addr);
- if (!GEP)
- return {};
- LLVM_DEBUG(dbgs() << "GEP\n");
- if (GEP->isUsedOutsideOfBlock(LoadI->getParent())) {
- LLVM_DEBUG(dbgs() << "used outside of block\n");
- return {};
- }
- const auto &DL = GEP->getModule()->getDataLayout();
- if (!isDereferenceablePointer(GEP, LoadI->getType(), DL)) {
+ const auto &DL = LoadI->getModule()->getDataLayout();
+ if (!isDereferenceablePointer(Addr, LoadI->getType(), DL)) {
LLVM_DEBUG(dbgs() << "not dereferenceable\n");
// We need to make sure that we can do comparison in any order, so we
// require memory to be unconditionnally dereferencable.
return {};
}
- APInt Offset = APInt(DL.getPointerTypeSizeInBits(GEP->getType()), 0);
- if (!GEP->accumulateConstantOffset(DL, Offset))
- return {};
- return BCEAtom(GEP, LoadI, BaseId.getBaseId(GEP->getPointerOperand()),
- Offset);
+
+ APInt Offset = APInt(DL.getPointerTypeSizeInBits(Addr->getType()), 0);
+ Value *Base = Addr;
+ auto *GEP = dyn_cast<GetElementPtrInst>(Addr);
+ if (GEP) {
+ LLVM_DEBUG(dbgs() << "GEP\n");
+ if (GEP->isUsedOutsideOfBlock(LoadI->getParent())) {
+ LLVM_DEBUG(dbgs() << "used outside of block\n");
+ return {};
+ }
+ if (!GEP->accumulateConstantOffset(DL, Offset))
+ return {};
+ Base = GEP->getPointerOperand();
+ }
+ return BCEAtom(GEP, LoadI, BaseId.getBaseId(Base), Offset);
}
// A comparison between two BCE atoms, e.g. `a == o.a` in the example at the
@@ -244,7 +246,7 @@ bool BCECmpBlock::canSinkBCECmpInst(const Instruction *Inst,
auto MayClobber = [&](LoadInst *LI) {
// If a potentially clobbering instruction comes before the load,
// we can still safely sink the load.
- return !Inst->comesBefore(LI) &&
+ return (Inst->getParent() != LI->getParent() || !Inst->comesBefore(LI)) &&
isModSet(AA.getModRefInfo(Inst, MemoryLocation::get(LI)));
};
if (MayClobber(Cmp.Lhs.LoadI) || MayClobber(Cmp.Rhs.LoadI))
@@ -270,9 +272,8 @@ void BCECmpBlock::split(BasicBlock *NewParent, AliasAnalysis &AA) const {
}
// Do the actual spliting.
- for (Instruction *Inst : reverse(OtherInsts)) {
- Inst->moveBefore(&*NewParent->begin());
- }
+ for (Instruction *Inst : reverse(OtherInsts))
+ Inst->moveBefore(*NewParent, NewParent->begin());
}
bool BCECmpBlock::canSplit(AliasAnalysis &AA) const {
@@ -368,8 +369,11 @@ Optional<BCECmpBlock> visitCmpBlock(Value *const Val, BasicBlock *const Block,
return None;
BCECmpBlock::InstructionSet BlockInsts(
- {Result->Lhs.GEP, Result->Rhs.GEP, Result->Lhs.LoadI, Result->Rhs.LoadI,
- Result->CmpI, BranchI});
+ {Result->Lhs.LoadI, Result->Rhs.LoadI, Result->CmpI, BranchI});
+ if (Result->Lhs.GEP)
+ BlockInsts.insert(Result->Lhs.GEP);
+ if (Result->Rhs.GEP)
+ BlockInsts.insert(Result->Rhs.GEP);
return BCECmpBlock(std::move(*Result), Block, BlockInsts);
}
@@ -604,8 +608,15 @@ static BasicBlock *mergeComparisons(ArrayRef<BCECmpBlock> Comparisons,
NextCmpBlock->getParent(), InsertBefore);
IRBuilder<> Builder(BB);
// Add the GEPs from the first BCECmpBlock.
- Value *const Lhs = Builder.Insert(FirstCmp.Lhs().GEP->clone());
- Value *const Rhs = Builder.Insert(FirstCmp.Rhs().GEP->clone());
+ Value *Lhs, *Rhs;
+ if (FirstCmp.Lhs().GEP)
+ Lhs = Builder.Insert(FirstCmp.Lhs().GEP->clone());
+ else
+ Lhs = FirstCmp.Lhs().LoadI->getPointerOperand();
+ if (FirstCmp.Rhs().GEP)
+ Rhs = Builder.Insert(FirstCmp.Rhs().GEP->clone());
+ else
+ Rhs = FirstCmp.Rhs().LoadI->getPointerOperand();
Value *IsEqual = nullptr;
LLVM_DEBUG(dbgs() << "Merging " << Comparisons.size() << " comparisons -> "