diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 95 |
1 files changed, 42 insertions, 53 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp index 0ab79a32f526..4e83d2f6e3c6 100644 --- a/contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -106,13 +106,8 @@ static Instruction *findCommonDominator(ArrayRef<Instruction *> Instructions, DominatorTree &DT) { Instruction *CommonDom = nullptr; for (auto *Insn : Instructions) - if (!CommonDom || DT.dominates(Insn, CommonDom)) - CommonDom = Insn; - else if (!DT.dominates(CommonDom, Insn)) - // If there is no dominance relation, use common dominator. - CommonDom = - DT.findNearestCommonDominator(CommonDom->getParent(), - Insn->getParent())->getTerminator(); + CommonDom = + CommonDom ? DT.findNearestCommonDominator(CommonDom, Insn) : Insn; assert(CommonDom && "Common dominator not found?"); return CommonDom; } @@ -195,6 +190,9 @@ Value *SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) bool SimplifyIndvar::makeIVComparisonInvariant(ICmpInst *ICmp, Instruction *IVOperand) { + auto *Preheader = L->getLoopPreheader(); + if (!Preheader) + return false; unsigned IVOperIdx = 0; ICmpInst::Predicate Pred = ICmp->getPredicate(); if (IVOperand != ICmp->getOperand(0)) { @@ -209,51 +207,22 @@ bool SimplifyIndvar::makeIVComparisonInvariant(ICmpInst *ICmp, const Loop *ICmpLoop = LI->getLoopFor(ICmp->getParent()); const SCEV *S = SE->getSCEVAtScope(ICmp->getOperand(IVOperIdx), ICmpLoop); const SCEV *X = SE->getSCEVAtScope(ICmp->getOperand(1 - IVOperIdx), ICmpLoop); - - auto *PN = dyn_cast<PHINode>(IVOperand); - if (!PN) - return false; - auto LIP = SE->getLoopInvariantPredicate(Pred, S, X, L); + auto LIP = SE->getLoopInvariantPredicate(Pred, S, X, L, ICmp); if (!LIP) return false; ICmpInst::Predicate InvariantPredicate = LIP->Pred; const SCEV *InvariantLHS = LIP->LHS; const SCEV *InvariantRHS = LIP->RHS; - // Rewrite the comparison to a loop invariant comparison if it can be done - // cheaply, where cheaply means "we don't need to emit any new - // instructions". - - SmallDenseMap<const SCEV*, Value*> CheapExpansions; - CheapExpansions[S] = ICmp->getOperand(IVOperIdx); - CheapExpansions[X] = ICmp->getOperand(1 - IVOperIdx); - - // TODO: Support multiple entry loops? (We currently bail out of these in - // the IndVarSimplify pass) - if (auto *BB = L->getLoopPredecessor()) { - const int Idx = PN->getBasicBlockIndex(BB); - if (Idx >= 0) { - Value *Incoming = PN->getIncomingValue(Idx); - const SCEV *IncomingS = SE->getSCEV(Incoming); - CheapExpansions[IncomingS] = Incoming; - } - } - Value *NewLHS = CheapExpansions[InvariantLHS]; - Value *NewRHS = CheapExpansions[InvariantRHS]; - - if (!NewLHS) - if (auto *ConstLHS = dyn_cast<SCEVConstant>(InvariantLHS)) - NewLHS = ConstLHS->getValue(); - if (!NewRHS) - if (auto *ConstRHS = dyn_cast<SCEVConstant>(InvariantRHS)) - NewRHS = ConstRHS->getValue(); - - if (!NewLHS || !NewRHS) - // We could not find an existing value to replace either LHS or RHS. - // Generating new instructions has subtler tradeoffs, so avoid doing that - // for now. + // Do not generate something ridiculous. + auto *PHTerm = Preheader->getTerminator(); + if (Rewriter.isHighCostExpansion({ InvariantLHS, InvariantRHS }, L, + 2 * SCEVCheapExpansionBudget, TTI, PHTerm)) return false; - + auto *NewLHS = + Rewriter.expandCodeFor(InvariantLHS, IVOperand->getType(), PHTerm); + auto *NewRHS = + Rewriter.expandCodeFor(InvariantRHS, IVOperand->getType(), PHTerm); LLVM_DEBUG(dbgs() << "INDVARS: Simplified comparison: " << *ICmp << '\n'); ICmp->setPredicate(InvariantPredicate); ICmp->setOperand(0, NewLHS); @@ -288,6 +257,7 @@ void SimplifyIndvar::eliminateIVComparison(ICmpInst *ICmp, Users.push_back(cast<Instruction>(U)); const Instruction *CtxI = findCommonDominator(Users, *DT); if (auto Ev = SE->evaluatePredicateAt(Pred, S, X, CtxI)) { + SE->forgetValue(ICmp); ICmp->replaceAllUsesWith(ConstantInt::getBool(ICmp->getContext(), *Ev)); DeadInsts.emplace_back(ICmp); LLVM_DEBUG(dbgs() << "INDVARS: Eliminated comparison: " << *ICmp << '\n'); @@ -683,7 +653,7 @@ bool SimplifyIndvar::replaceFloatIVWithIntegerIV(Instruction *UseInst) { UseInst->getOpcode() != CastInst::UIToFP) return false; - Value *IVOperand = UseInst->getOperand(0); + Instruction *IVOperand = cast<Instruction>(UseInst->getOperand(0)); // Get the symbolic expression for this instruction. const SCEV *IV = SE->getSCEV(IVOperand); unsigned MaskBits; @@ -696,17 +666,35 @@ bool SimplifyIndvar::replaceFloatIVWithIntegerIV(Instruction *UseInst) { for (User *U : UseInst->users()) { // Match for fptosi/fptoui of sitofp and with same type. auto *CI = dyn_cast<CastInst>(U); - if (!CI || IVOperand->getType() != CI->getType()) + if (!CI) continue; CastInst::CastOps Opcode = CI->getOpcode(); if (Opcode != CastInst::FPToSI && Opcode != CastInst::FPToUI) continue; - CI->replaceAllUsesWith(IVOperand); + Value *Conv = nullptr; + if (IVOperand->getType() != CI->getType()) { + IRBuilder<> Builder(CI); + StringRef Name = IVOperand->getName(); + // To match InstCombine logic, we only need sext if both fptosi and + // sitofp are used. If one of them is unsigned, then we can use zext. + if (SE->getTypeSizeInBits(IVOperand->getType()) > + SE->getTypeSizeInBits(CI->getType())) { + Conv = Builder.CreateTrunc(IVOperand, CI->getType(), Name + ".trunc"); + } else if (Opcode == CastInst::FPToUI || + UseInst->getOpcode() == CastInst::UIToFP) { + Conv = Builder.CreateZExt(IVOperand, CI->getType(), Name + ".zext"); + } else { + Conv = Builder.CreateSExt(IVOperand, CI->getType(), Name + ".sext"); + } + } else + Conv = IVOperand; + + CI->replaceAllUsesWith(Conv); DeadInsts.push_back(CI); LLVM_DEBUG(dbgs() << "INDVARS: Replace IV user: " << *CI - << " with: " << *IVOperand << '\n'); + << " with: " << *Conv << '\n'); ++NumFoldedUser; Changed = true; @@ -751,6 +739,7 @@ bool SimplifyIndvar::eliminateIdentitySCEV(Instruction *UseInst, LLVM_DEBUG(dbgs() << "INDVARS: Eliminated identity: " << *UseInst << '\n'); + SE->forgetValue(UseInst); UseInst->replaceAllUsesWith(IVOperand); ++NumElimIdentity; Changed = true; @@ -1041,13 +1030,13 @@ class WidenIV { // context. DenseMap<DefUserPair, ConstantRange> PostIncRangeInfos; - Optional<ConstantRange> getPostIncRangeInfo(Value *Def, - Instruction *UseI) { + std::optional<ConstantRange> getPostIncRangeInfo(Value *Def, + Instruction *UseI) { DefUserPair Key(Def, UseI); auto It = PostIncRangeInfos.find(Key); return It == PostIncRangeInfos.end() - ? Optional<ConstantRange>(None) - : Optional<ConstantRange>(It->second); + ? std::optional<ConstantRange>(std::nullopt) + : std::optional<ConstantRange>(It->second); } void calculatePostIncRanges(PHINode *OrigPhi); |