diff options
Diffstat (limited to 'llvm/lib/Transforms/Scalar/MergeICmps.cpp')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/MergeICmps.cpp | 59 |
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 -> " |
