From b4624f65cfcb5b17226d0a330692570f8618ca69 Mon Sep 17 00:00:00 2001 From: Max Kazantsev Date: Mon, 16 Nov 2020 13:41:13 +0700 Subject: [PATCH] Recommit "[NFC] Move code between functions as a preparation step for further improvement" The bug should be fixed now. --- llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 119 +++++++----------- 1 file changed, 44 insertions(+), 75 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp index cc8a9976c30369..e36d2e7f3a5b58 100644 --- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1290,66 +1290,6 @@ bool IndVarSimplify::sinkUnusedInvariants(Loop *L) { return MadeAnyChanges; } -enum ExitCondAnalysisResult { - CanBeRemoved, - CanBeReplacedWithInvariant, - CannotOptimize -}; - -/// If the condition of BI is trivially true during at least first MaxIter -/// iterations, return CanBeRemoved. -/// If the condition is equivalent to loop-invariant condition expressed as -/// 'InvariantLHS `InvariantPred` InvariantRHS', fill them into respective -/// output parameters and return CanBeReplacedWithInvariant. -/// Otherwise, return CannotOptimize. -static ExitCondAnalysisResult -analyzeCond(const Loop *L, BranchInst *BI, ScalarEvolution *SE, - bool ProvingLoopExit, const SCEV *MaxIter, - ICmpInst::Predicate &InvariantPred, const SCEV *&InvariantLHS, - const SCEV *&InvariantRHS) { - ICmpInst::Predicate Pred; - Value *LHS, *RHS; - using namespace PatternMatch; - BasicBlock *TrueSucc, *FalseSucc; - if (!match(BI, m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)), - m_BasicBlock(TrueSucc), m_BasicBlock(FalseSucc)))) - return CannotOptimize; - - assert((L->contains(TrueSucc) != L->contains(FalseSucc)) && - "Not a loop exit!"); - - // 'LHS pred RHS' should now mean that we stay in loop. - if (L->contains(FalseSucc)) - Pred = CmpInst::getInversePredicate(Pred); - - // If we are proving loop exit, invert the predicate. - if (ProvingLoopExit) - Pred = CmpInst::getInversePredicate(Pred); - - const SCEV *LHSS = SE->getSCEVAtScope(LHS, L); - const SCEV *RHSS = SE->getSCEVAtScope(RHS, L); - // Can we prove it to be trivially true? - if (SE->isKnownPredicateAt(Pred, LHSS, RHSS, BI)) - return CanBeRemoved; - - if (ProvingLoopExit) - return CannotOptimize; - - // Check if there is a loop-invariant predicate equivalent to our check. - auto LIP = SE->getLoopInvariantExitCondDuringFirstIterations(Pred, LHSS, RHSS, - L, BI, MaxIter); - if (!LIP) - return CannotOptimize; - InvariantPred = LIP->Pred; - InvariantLHS = LIP->LHS; - InvariantRHS = LIP->RHS; - - // Can we prove it to be trivially true? - if (SE->isKnownPredicateAt(InvariantPred, InvariantLHS, InvariantRHS, BI)) - return CanBeRemoved; - return CanBeReplacedWithInvariant; -} - static void replaceExitCond(BranchInst *BI, Value *NewCond, SmallVectorImpl &DeadInsts) { auto *OldCond = BI->getCondition(); @@ -1390,26 +1330,55 @@ static bool optimizeLoopExitWithUnknownExitCount( const SCEV *MaxIter, bool Inverted, bool SkipLastIter, ScalarEvolution *SE, SCEVExpander &Rewriter, SmallVectorImpl &DeadInsts) { - if (SkipLastIter) { - const SCEV *One = SE->getOne(MaxIter->getType()); - MaxIter = SE->getMinusSCEV(MaxIter, One); - } - ICmpInst::Predicate InvariantPred; - const SCEV *InvariantLHS, *InvariantRHS; - switch (analyzeCond(L, BI, SE, Inverted, MaxIter, InvariantPred, InvariantLHS, - InvariantRHS)) { - case CanBeRemoved: + ICmpInst::Predicate Pred; + Value *LHS, *RHS; + using namespace PatternMatch; + BasicBlock *TrueSucc, *FalseSucc; + if (!match(BI, m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)), + m_BasicBlock(TrueSucc), m_BasicBlock(FalseSucc)))) + return false; + + assert((L->contains(TrueSucc) != L->contains(FalseSucc)) && + "Not a loop exit!"); + + // 'LHS pred RHS' should now mean that we stay in loop. + if (L->contains(FalseSucc)) + Pred = CmpInst::getInversePredicate(Pred); + + // If we are proving loop exit, invert the predicate. + if (Inverted) + Pred = CmpInst::getInversePredicate(Pred); + + const SCEV *LHSS = SE->getSCEVAtScope(LHS, L); + const SCEV *RHSS = SE->getSCEVAtScope(RHS, L); + // Can we prove it to be trivially true? + if (SE->isKnownPredicateAt(Pred, LHSS, RHSS, BI)) { foldExit(L, ExitingBB, Inverted, DeadInsts); return true; - case CanBeReplacedWithInvariant: { - replaceWithInvariantCond(L, ExitingBB, InvariantPred, InvariantLHS, - InvariantRHS, Rewriter, DeadInsts); - return true; } - case CannotOptimize: + // Further logic works for non-inverted condition only. + if (Inverted) return false; + + if (SkipLastIter) { + const SCEV *One = SE->getOne(MaxIter->getType()); + MaxIter = SE->getMinusSCEV(MaxIter, One); } - llvm_unreachable("Unknown case!"); + + // Check if there is a loop-invariant predicate equivalent to our check. + auto LIP = SE->getLoopInvariantExitCondDuringFirstIterations(Pred, LHSS, RHSS, + L, BI, MaxIter); + if (!LIP) + return false; + + // Can we prove it to be trivially true? + if (SE->isKnownPredicateAt(LIP->Pred, LIP->LHS, LIP->RHS, BI)) + foldExit(L, ExitingBB, Inverted, DeadInsts); + else + replaceWithInvariantCond(L, ExitingBB, LIP->Pred, LIP->LHS, LIP->RHS, + Rewriter, DeadInsts); + + return true; } bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {