1818#include " llvm/ADT/Statistic.h"
1919#include " llvm/Analysis/ConstraintSystem.h"
2020#include " llvm/Analysis/GlobalsModRef.h"
21+ #include " llvm/Analysis/LoopInfo.h"
2122#include " llvm/Analysis/OptimizationRemarkEmitter.h"
23+ #include " llvm/Analysis/ScalarEvolution.h"
24+ #include " llvm/Analysis/ScalarEvolutionExpressions.h"
2225#include " llvm/Analysis/ValueTracking.h"
2326#include " llvm/IR/DataLayout.h"
2427#include " llvm/IR/Dominators.h"
@@ -89,6 +92,8 @@ struct ConditionTy {
8992 Value *Op0;
9093 Value *Op1;
9194
95+ ConditionTy ()
96+ : Pred(CmpInst::BAD_ICMP_PREDICATE), Op0(nullptr ), Op1(nullptr ) {}
9297 ConditionTy (CmpInst::Predicate Pred, Value *Op0, Value *Op1)
9398 : Pred(Pred), Op0(Op0), Op1(Op1) {}
9499};
@@ -114,6 +119,10 @@ struct FactOrCheck {
114119 ConditionTy Cond;
115120 };
116121
122+ // / A pre-condition that must hold for the current fact to be added to the
123+ // / system.
124+ ConditionTy DoesHold;
125+
117126 unsigned NumIn;
118127 unsigned NumOut;
119128 EntryTy Ty;
@@ -123,27 +132,25 @@ struct FactOrCheck {
123132 Ty(Ty) {}
124133
125134 FactOrCheck (DomTreeNode *DTN, Use *U)
126- : U(U), NumIn(DTN->getDFSNumIn ()), NumOut(DTN->getDFSNumOut ()),
135+ : U(U), DoesHold(CmpInst::BAD_ICMP_PREDICATE, nullptr , nullptr ),
136+ NumIn(DTN->getDFSNumIn ()), NumOut(DTN->getDFSNumOut ()),
127137 Ty(EntryTy::UseCheck) {}
128138
129- FactOrCheck (DomTreeNode *DTN, CmpInst::Predicate Pred, Value *Op0, Value *Op1)
130- : Cond(Pred, Op0, Op1), NumIn(DTN->getDFSNumIn ()),
139+ FactOrCheck (DomTreeNode *DTN, CmpInst::Predicate Pred, Value *Op0, Value *Op1,
140+ ConditionTy Precond = ConditionTy())
141+ : Cond(Pred, Op0, Op1), DoesHold(Precond), NumIn(DTN->getDFSNumIn ()),
131142 NumOut(DTN->getDFSNumOut ()), Ty(EntryTy::ConditionFact) {}
132143
133144 static FactOrCheck getConditionFact (DomTreeNode *DTN, CmpInst::Predicate Pred,
134- Value *Op0, Value *Op1) {
135- return FactOrCheck (DTN, Pred, Op0, Op1);
145+ Value *Op0, Value *Op1,
146+ ConditionTy Precond = ConditionTy()) {
147+ return FactOrCheck (DTN, Pred, Op0, Op1, Precond);
136148 }
137149
138150 static FactOrCheck getInstFact (DomTreeNode *DTN, Instruction *Inst) {
139151 return FactOrCheck (EntryTy::InstFact, DTN, Inst);
140152 }
141153
142- static FactOrCheck getFact (DomTreeNode *DTN, CmpInst::Predicate Pred,
143- Value *Op0, Value *Op1) {
144- return FactOrCheck (DTN, Pred, Op0, Op1);
145- }
146-
147154 static FactOrCheck getCheck (DomTreeNode *DTN, Use *U) {
148155 return FactOrCheck (DTN, U);
149156 }
@@ -176,13 +183,20 @@ struct FactOrCheck {
176183// / Keep state required to build worklist.
177184struct State {
178185 DominatorTree &DT;
186+ LoopInfo &LI;
187+ ScalarEvolution &SE;
179188 SmallVector<FactOrCheck, 64 > WorkList;
180189
181- State (DominatorTree &DT) : DT(DT) {}
190+ State (DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE)
191+ : DT(DT), LI(LI), SE(SE) {}
182192
183193 // / Process block \p BB and add known facts to work-list.
184194 void addInfoFor (BasicBlock &BB);
185195
196+ // / Try to add facts for loop inductions (AddRecs) in EQ/NE compares
197+ // / controlling the loop header.
198+ void addInfoForInductions (BasicBlock &BB);
199+
186200 // / Returns true if we can add a known condition from BB to its successor
187201 // / block Succ.
188202 bool canAddSuccessor (BasicBlock &BB, BasicBlock *Succ) const {
@@ -786,7 +800,114 @@ static void dumpConstraint(ArrayRef<int64_t> C,
786800}
787801#endif
788802
803+ void State::addInfoForInductions (BasicBlock &BB) {
804+ auto *L = LI.getLoopFor (&BB);
805+ if (!L || L->getHeader () != &BB)
806+ return ;
807+
808+ Value *A;
809+ Value *B;
810+ CmpInst::Predicate Pred;
811+
812+ if (!match (BB.getTerminator (),
813+ m_Br (m_ICmp (Pred, m_Value (A), m_Value (B)), m_Value (), m_Value ())))
814+ return ;
815+ PHINode *PN = dyn_cast<PHINode>(A);
816+ if (!PN) {
817+ Pred = CmpInst::getSwappedPredicate (Pred);
818+ std::swap (A, B);
819+ PN = dyn_cast<PHINode>(A);
820+ }
821+
822+ if (!PN || PN->getParent () != &BB || PN->getNumIncomingValues () != 2 ||
823+ !SE.isSCEVable (PN->getType ()))
824+ return ;
825+
826+ BasicBlock *InLoopSucc = nullptr ;
827+ if (Pred == CmpInst::ICMP_NE)
828+ InLoopSucc = cast<BranchInst>(BB.getTerminator ())->getSuccessor (0 );
829+ else if (Pred == CmpInst::ICMP_EQ)
830+ InLoopSucc = cast<BranchInst>(BB.getTerminator ())->getSuccessor (1 );
831+ else
832+ return ;
833+
834+ if (!L->contains (InLoopSucc) || !L->isLoopExiting (&BB) || InLoopSucc == &BB)
835+ return ;
836+
837+ auto *AR = dyn_cast_or_null<SCEVAddRecExpr>(SE.getSCEV (PN));
838+ if (!AR)
839+ return ;
840+
841+ const SCEV *StartSCEV = AR->getStart ();
842+ Value *StartValue = nullptr ;
843+ if (auto *C = dyn_cast<SCEVConstant>(StartSCEV))
844+ StartValue = C->getValue ();
845+ else if (auto *U = dyn_cast<SCEVUnknown>(StartSCEV))
846+ StartValue = U->getValue ();
847+
848+ if (!StartValue)
849+ return ;
850+
851+ DomTreeNode *DTN = DT.getNode (InLoopSucc);
852+ auto Inc = SE.getMonotonicPredicateType (AR, CmpInst::ICMP_UGT);
853+ bool MonotonicallyIncreasing =
854+ Inc && *Inc == ScalarEvolution::MonotonicallyIncreasing;
855+ if (MonotonicallyIncreasing) {
856+ // SCEV guarantees that AR does not wrap, so PN >= StartValue can be added
857+ // unconditionally.
858+ WorkList.push_back (
859+ FactOrCheck::getConditionFact (DTN, CmpInst::ICMP_UGE, PN, StartValue));
860+ }
861+
862+ APInt StepOffset;
863+ if (auto *C = dyn_cast<SCEVConstant>(AR->getStepRecurrence (SE)))
864+ StepOffset = C->getAPInt ();
865+ else
866+ return ;
867+
868+ // Make sure AR either steps by 1 or that the value we compare against is a
869+ // GEP based on the same start value and all offsets are a multiple of the
870+ // step size, to guarantee that the induction will reach the value.
871+ if (StepOffset.isZero () || StepOffset.isNegative ())
872+ return ;
873+
874+ if (!StepOffset.isOne ()) {
875+ auto *UpperGEP = dyn_cast<GetElementPtrInst>(B);
876+ if (!UpperGEP || UpperGEP->getPointerOperand () != StartValue ||
877+ !UpperGEP->isInBounds ())
878+ return ;
879+
880+ MapVector<Value *, APInt> UpperVariableOffsets;
881+ APInt UpperConstantOffset (StepOffset.getBitWidth (), 0 );
882+ const DataLayout &DL = BB.getModule ()->getDataLayout ();
883+ if (!UpperGEP->collectOffset (DL, StepOffset.getBitWidth (),
884+ UpperVariableOffsets, UpperConstantOffset))
885+ return ;
886+ // All variable offsets and the constant offset have to be a multiple of the
887+ // step.
888+ if (!UpperConstantOffset.urem (StepOffset).isZero () ||
889+ any_of (UpperVariableOffsets, [&StepOffset](const auto &P) {
890+ return !P.second .urem (StepOffset).isZero ();
891+ }))
892+ return ;
893+ }
894+
895+ // AR may wrap. Add PN >= StartValue conditional on StartValue <= B which
896+ // guarantees that the loop exits before wrapping in combination with the
897+ // restrictions on B and the step above.
898+ if (!MonotonicallyIncreasing) {
899+ WorkList.push_back (FactOrCheck::getConditionFact (
900+ DTN, CmpInst::ICMP_UGE, PN, StartValue,
901+ ConditionTy (CmpInst::ICMP_ULE, StartValue, B)));
902+ }
903+ WorkList.push_back (FactOrCheck::getConditionFact (
904+ DTN, CmpInst::ICMP_ULT, PN, B,
905+ ConditionTy (CmpInst::ICMP_ULE, StartValue, B)));
906+ }
907+
789908void State::addInfoFor (BasicBlock &BB) {
909+ addInfoForInductions (BB);
910+
790911 // True as long as long as the current instruction is guaranteed to execute.
791912 bool GuaranteedToExecute = true ;
792913 // Queue conditions and assumes.
@@ -1154,6 +1275,7 @@ static bool checkAndSecondOpImpliedByFirst(
11541275 FactOrCheck &CB, ConstraintInfo &Info, Module *ReproducerModule,
11551276 SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
11561277 SmallVectorImpl<StackEntry> &DFSInStack) {
1278+
11571279 CmpInst::Predicate Pred;
11581280 Value *A, *B;
11591281 Instruction *And = CB.getContextInst ();
@@ -1297,15 +1419,16 @@ tryToSimplifyOverflowMath(IntrinsicInst *II, ConstraintInfo &Info,
12971419 return Changed;
12981420}
12991421
1300- static bool eliminateConstraints (Function &F, DominatorTree &DT,
1422+ static bool eliminateConstraints (Function &F, DominatorTree &DT, LoopInfo &LI,
1423+ ScalarEvolution &SE,
13011424 OptimizationRemarkEmitter &ORE) {
13021425 bool Changed = false ;
13031426 DT.updateDFSNumbers ();
13041427 SmallVector<Value *> FunctionArgs;
13051428 for (Value &Arg : F.args ())
13061429 FunctionArgs.push_back (&Arg);
13071430 ConstraintInfo Info (F.getParent ()->getDataLayout (), FunctionArgs);
1308- State S (DT);
1431+ State S (DT, LI, SE );
13091432 std::unique_ptr<Module> ReproducerModule (
13101433 DumpReproducers ? new Module (F.getName (), F.getContext ()) : nullptr );
13111434
@@ -1403,6 +1526,10 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT,
14031526 }
14041527
14051528 auto AddFact = [&](CmpInst::Predicate Pred, Value *A, Value *B) {
1529+ LLVM_DEBUG (dbgs () << " fact to add to the system: "
1530+ << CmpInst::getPredicateName (Pred) << " " ;
1531+ A->printAsOperand (dbgs ()); dbgs () << " , " ;
1532+ B->printAsOperand (dbgs ()); dbgs () << " \n " );
14061533 if (Info.getCS (CmpInst::isSigned (Pred)).size () > MaxRows) {
14071534 LLVM_DEBUG (
14081535 dbgs ()
@@ -1450,6 +1577,9 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT,
14501577 Pred = CB.Cond .Pred ;
14511578 A = CB.Cond .Op0 ;
14521579 B = CB.Cond .Op1 ;
1580+ if (CB.DoesHold .Pred != CmpInst::BAD_ICMP_PREDICATE &&
1581+ !Info.doesHold (CB.DoesHold .Pred , CB.DoesHold .Op0 , CB.DoesHold .Op1 ))
1582+ continue ;
14531583 } else {
14541584 bool Matched = match (CB.Inst , m_Intrinsic<Intrinsic::assume>(
14551585 m_ICmp (Pred, m_Value (A), m_Value (B))));
@@ -1486,12 +1616,16 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT,
14861616PreservedAnalyses ConstraintEliminationPass::run (Function &F,
14871617 FunctionAnalysisManager &AM) {
14881618 auto &DT = AM.getResult <DominatorTreeAnalysis>(F);
1619+ auto &LI = AM.getResult <LoopAnalysis>(F);
1620+ auto &SE = AM.getResult <ScalarEvolutionAnalysis>(F);
14891621 auto &ORE = AM.getResult <OptimizationRemarkEmitterAnalysis>(F);
1490- if (!eliminateConstraints (F, DT, ORE))
1622+ if (!eliminateConstraints (F, DT, LI, SE, ORE))
14911623 return PreservedAnalyses::all ();
14921624
14931625 PreservedAnalyses PA;
14941626 PA.preserve <DominatorTreeAnalysis>();
1627+ PA.preserve <LoopAnalysis>();
1628+ PA.preserve <ScalarEvolutionAnalysis>();
14951629 PA.preserveSet <CFGAnalyses>();
14961630 return PA;
14971631}
0 commit comments