18
18
#include " llvm/ADT/Statistic.h"
19
19
#include " llvm/Analysis/ConstraintSystem.h"
20
20
#include " llvm/Analysis/GlobalsModRef.h"
21
+ #include " llvm/Analysis/LoopInfo.h"
21
22
#include " llvm/Analysis/OptimizationRemarkEmitter.h"
23
+ #include " llvm/Analysis/ScalarEvolution.h"
24
+ #include " llvm/Analysis/ScalarEvolutionExpressions.h"
22
25
#include " llvm/Analysis/ValueTracking.h"
23
26
#include " llvm/IR/DataLayout.h"
24
27
#include " llvm/IR/Dominators.h"
@@ -90,6 +93,8 @@ struct ConditionTy {
90
93
Value *Op0;
91
94
Value *Op1;
92
95
96
+ ConditionTy ()
97
+ : Pred(CmpInst::BAD_ICMP_PREDICATE), Op0(nullptr ), Op1(nullptr ) {}
93
98
ConditionTy (CmpInst::Predicate Pred, Value *Op0, Value *Op1)
94
99
: Pred(Pred), Op0(Op0), Op1(Op1) {}
95
100
};
@@ -115,6 +120,10 @@ struct FactOrCheck {
115
120
ConditionTy Cond;
116
121
};
117
122
123
+ // / A pre-condition that must hold for the current fact to be added to the
124
+ // / system.
125
+ ConditionTy DoesHold;
126
+
118
127
unsigned NumIn;
119
128
unsigned NumOut;
120
129
EntryTy Ty;
@@ -124,27 +133,25 @@ struct FactOrCheck {
124
133
Ty(Ty) {}
125
134
126
135
FactOrCheck (DomTreeNode *DTN, Use *U)
127
- : U(U), NumIn(DTN->getDFSNumIn ()), NumOut(DTN->getDFSNumOut ()),
136
+ : U(U), DoesHold(CmpInst::BAD_ICMP_PREDICATE, nullptr , nullptr ),
137
+ NumIn(DTN->getDFSNumIn ()), NumOut(DTN->getDFSNumOut ()),
128
138
Ty(EntryTy::UseCheck) {}
129
139
130
- FactOrCheck (DomTreeNode *DTN, CmpInst::Predicate Pred, Value *Op0, Value *Op1)
131
- : Cond(Pred, Op0, Op1), NumIn(DTN->getDFSNumIn ()),
140
+ FactOrCheck (DomTreeNode *DTN, CmpInst::Predicate Pred, Value *Op0, Value *Op1,
141
+ ConditionTy Precond = ConditionTy())
142
+ : Cond(Pred, Op0, Op1), DoesHold(Precond), NumIn(DTN->getDFSNumIn ()),
132
143
NumOut(DTN->getDFSNumOut ()), Ty(EntryTy::ConditionFact) {}
133
144
134
145
static FactOrCheck getConditionFact (DomTreeNode *DTN, CmpInst::Predicate Pred,
135
- Value *Op0, Value *Op1) {
136
- return FactOrCheck (DTN, Pred, Op0, Op1);
146
+ Value *Op0, Value *Op1,
147
+ ConditionTy Precond = ConditionTy()) {
148
+ return FactOrCheck (DTN, Pred, Op0, Op1, Precond);
137
149
}
138
150
139
151
static FactOrCheck getInstFact (DomTreeNode *DTN, Instruction *Inst) {
140
152
return FactOrCheck (EntryTy::InstFact, DTN, Inst);
141
153
}
142
154
143
- static FactOrCheck getFact (DomTreeNode *DTN, CmpInst::Predicate Pred,
144
- Value *Op0, Value *Op1) {
145
- return FactOrCheck (DTN, Pred, Op0, Op1);
146
- }
147
-
148
155
static FactOrCheck getCheck (DomTreeNode *DTN, Use *U) {
149
156
return FactOrCheck (DTN, U);
150
157
}
@@ -177,13 +184,20 @@ struct FactOrCheck {
177
184
// / Keep state required to build worklist.
178
185
struct State {
179
186
DominatorTree &DT;
187
+ LoopInfo &LI;
188
+ ScalarEvolution &SE;
180
189
SmallVector<FactOrCheck, 64 > WorkList;
181
190
182
- State (DominatorTree &DT) : DT(DT) {}
191
+ State (DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE)
192
+ : DT(DT), LI(LI), SE(SE) {}
183
193
184
194
// / Process block \p BB and add known facts to work-list.
185
195
void addInfoFor (BasicBlock &BB);
186
196
197
+ // / Try to add facts for loop inductions (AddRecs) in EQ/NE compares
198
+ // / controlling the loop header.
199
+ void addInfoForInductions (BasicBlock &BB);
200
+
187
201
// / Returns true if we can add a known condition from BB to its successor
188
202
// / block Succ.
189
203
bool canAddSuccessor (BasicBlock &BB, BasicBlock *Succ) const {
@@ -799,7 +813,114 @@ static void dumpConstraint(ArrayRef<int64_t> C,
799
813
}
800
814
#endif
801
815
816
+ void State::addInfoForInductions (BasicBlock &BB) {
817
+ auto *L = LI.getLoopFor (&BB);
818
+ if (!L || L->getHeader () != &BB)
819
+ return ;
820
+
821
+ Value *A;
822
+ Value *B;
823
+ CmpInst::Predicate Pred;
824
+
825
+ if (!match (BB.getTerminator (),
826
+ m_Br (m_ICmp (Pred, m_Value (A), m_Value (B)), m_Value (), m_Value ())))
827
+ return ;
828
+ PHINode *PN = dyn_cast<PHINode>(A);
829
+ if (!PN) {
830
+ Pred = CmpInst::getSwappedPredicate (Pred);
831
+ std::swap (A, B);
832
+ PN = dyn_cast<PHINode>(A);
833
+ }
834
+
835
+ if (!PN || PN->getParent () != &BB || PN->getNumIncomingValues () != 2 ||
836
+ !SE.isSCEVable (PN->getType ()))
837
+ return ;
838
+
839
+ BasicBlock *InLoopSucc = nullptr ;
840
+ if (Pred == CmpInst::ICMP_NE)
841
+ InLoopSucc = cast<BranchInst>(BB.getTerminator ())->getSuccessor (0 );
842
+ else if (Pred == CmpInst::ICMP_EQ)
843
+ InLoopSucc = cast<BranchInst>(BB.getTerminator ())->getSuccessor (1 );
844
+ else
845
+ return ;
846
+
847
+ if (!L->contains (InLoopSucc) || !L->isLoopExiting (&BB) || InLoopSucc == &BB)
848
+ return ;
849
+
850
+ auto *AR = dyn_cast_or_null<SCEVAddRecExpr>(SE.getSCEV (PN));
851
+ if (!AR)
852
+ return ;
853
+
854
+ const SCEV *StartSCEV = AR->getStart ();
855
+ Value *StartValue = nullptr ;
856
+ if (auto *C = dyn_cast<SCEVConstant>(StartSCEV))
857
+ StartValue = C->getValue ();
858
+ else if (auto *U = dyn_cast<SCEVUnknown>(StartSCEV))
859
+ StartValue = U->getValue ();
860
+
861
+ if (!StartValue)
862
+ return ;
863
+
864
+ DomTreeNode *DTN = DT.getNode (InLoopSucc);
865
+ auto Inc = SE.getMonotonicPredicateType (AR, CmpInst::ICMP_UGT);
866
+ bool MonotonicallyIncreasing =
867
+ Inc && *Inc == ScalarEvolution::MonotonicallyIncreasing;
868
+ if (MonotonicallyIncreasing) {
869
+ // SCEV guarantees that AR does not wrap, so PN >= StartValue can be added
870
+ // unconditionally.
871
+ WorkList.push_back (
872
+ FactOrCheck::getConditionFact (DTN, CmpInst::ICMP_UGE, PN, StartValue));
873
+ }
874
+
875
+ APInt StepOffset;
876
+ if (auto *C = dyn_cast<SCEVConstant>(AR->getStepRecurrence (SE)))
877
+ StepOffset = C->getAPInt ();
878
+ else
879
+ return ;
880
+
881
+ // Make sure AR either steps by 1 or that the value we compare against is a
882
+ // GEP based on the same start value and all offsets are a multiple of the
883
+ // step size, to guarantee that the induction will reach the value.
884
+ if (StepOffset.isZero () || StepOffset.isNegative ())
885
+ return ;
886
+
887
+ if (!StepOffset.isOne ()) {
888
+ auto *UpperGEP = dyn_cast<GetElementPtrInst>(B);
889
+ if (!UpperGEP || UpperGEP->getPointerOperand () != StartValue ||
890
+ !UpperGEP->isInBounds ())
891
+ return ;
892
+
893
+ MapVector<Value *, APInt> UpperVariableOffsets;
894
+ APInt UpperConstantOffset (StepOffset.getBitWidth (), 0 );
895
+ const DataLayout &DL = BB.getModule ()->getDataLayout ();
896
+ if (!UpperGEP->collectOffset (DL, StepOffset.getBitWidth (),
897
+ UpperVariableOffsets, UpperConstantOffset))
898
+ return ;
899
+ // All variable offsets and the constant offset have to be a multiple of the
900
+ // step.
901
+ if (!UpperConstantOffset.urem (StepOffset).isZero () ||
902
+ any_of (UpperVariableOffsets, [&StepOffset](const auto &P) {
903
+ return !P.second .urem (StepOffset).isZero ();
904
+ }))
905
+ return ;
906
+ }
907
+
908
+ // AR may wrap. Add PN >= StartValue conditional on StartValue <= B which
909
+ // guarantees that the loop exits before wrapping in combination with the
910
+ // restrictions on B and the step above.
911
+ if (!MonotonicallyIncreasing) {
912
+ WorkList.push_back (FactOrCheck::getConditionFact (
913
+ DTN, CmpInst::ICMP_UGE, PN, StartValue,
914
+ ConditionTy (CmpInst::ICMP_ULE, StartValue, B)));
915
+ }
916
+ WorkList.push_back (FactOrCheck::getConditionFact (
917
+ DTN, CmpInst::ICMP_ULT, PN, B,
918
+ ConditionTy (CmpInst::ICMP_ULE, StartValue, B)));
919
+ }
920
+
802
921
void State::addInfoFor (BasicBlock &BB) {
922
+ addInfoForInductions (BB);
923
+
803
924
// True as long as long as the current instruction is guaranteed to execute.
804
925
bool GuaranteedToExecute = true ;
805
926
// Queue conditions and assumes.
@@ -1179,6 +1300,7 @@ static bool checkAndSecondOpImpliedByFirst(
1179
1300
FactOrCheck &CB, ConstraintInfo &Info, Module *ReproducerModule,
1180
1301
SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
1181
1302
SmallVectorImpl<StackEntry> &DFSInStack) {
1303
+
1182
1304
CmpInst::Predicate Pred;
1183
1305
Value *A, *B;
1184
1306
Instruction *And = CB.getContextInst ();
@@ -1322,15 +1444,16 @@ tryToSimplifyOverflowMath(IntrinsicInst *II, ConstraintInfo &Info,
1322
1444
return Changed;
1323
1445
}
1324
1446
1325
- static bool eliminateConstraints (Function &F, DominatorTree &DT,
1447
+ static bool eliminateConstraints (Function &F, DominatorTree &DT, LoopInfo &LI,
1448
+ ScalarEvolution &SE,
1326
1449
OptimizationRemarkEmitter &ORE) {
1327
1450
bool Changed = false ;
1328
1451
DT.updateDFSNumbers ();
1329
1452
SmallVector<Value *> FunctionArgs;
1330
1453
for (Value &Arg : F.args ())
1331
1454
FunctionArgs.push_back (&Arg);
1332
1455
ConstraintInfo Info (F.getParent ()->getDataLayout (), FunctionArgs);
1333
- State S (DT);
1456
+ State S (DT, LI, SE );
1334
1457
std::unique_ptr<Module> ReproducerModule (
1335
1458
DumpReproducers ? new Module (F.getName (), F.getContext ()) : nullptr );
1336
1459
@@ -1428,6 +1551,10 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT,
1428
1551
}
1429
1552
1430
1553
auto AddFact = [&](CmpInst::Predicate Pred, Value *A, Value *B) {
1554
+ LLVM_DEBUG (dbgs () << " fact to add to the system: "
1555
+ << CmpInst::getPredicateName (Pred) << " " ;
1556
+ A->printAsOperand (dbgs ()); dbgs () << " , " ;
1557
+ B->printAsOperand (dbgs ()); dbgs () << " \n " );
1431
1558
if (Info.getCS (CmpInst::isSigned (Pred)).size () > MaxRows) {
1432
1559
LLVM_DEBUG (
1433
1560
dbgs ()
@@ -1475,6 +1602,9 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT,
1475
1602
Pred = CB.Cond .Pred ;
1476
1603
A = CB.Cond .Op0 ;
1477
1604
B = CB.Cond .Op1 ;
1605
+ if (CB.DoesHold .Pred != CmpInst::BAD_ICMP_PREDICATE &&
1606
+ !Info.doesHold (CB.DoesHold .Pred , CB.DoesHold .Op0 , CB.DoesHold .Op1 ))
1607
+ continue ;
1478
1608
} else {
1479
1609
bool Matched = match (CB.Inst , m_Intrinsic<Intrinsic::assume>(
1480
1610
m_ICmp (Pred, m_Value (A), m_Value (B))));
@@ -1511,12 +1641,16 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT,
1511
1641
PreservedAnalyses ConstraintEliminationPass::run (Function &F,
1512
1642
FunctionAnalysisManager &AM) {
1513
1643
auto &DT = AM.getResult <DominatorTreeAnalysis>(F);
1644
+ auto &LI = AM.getResult <LoopAnalysis>(F);
1645
+ auto &SE = AM.getResult <ScalarEvolutionAnalysis>(F);
1514
1646
auto &ORE = AM.getResult <OptimizationRemarkEmitterAnalysis>(F);
1515
- if (!eliminateConstraints (F, DT, ORE))
1647
+ if (!eliminateConstraints (F, DT, LI, SE, ORE))
1516
1648
return PreservedAnalyses::all ();
1517
1649
1518
1650
PreservedAnalyses PA;
1519
1651
PA.preserve <DominatorTreeAnalysis>();
1652
+ PA.preserve <LoopAnalysis>();
1653
+ PA.preserve <ScalarEvolutionAnalysis>();
1520
1654
PA.preserveSet <CFGAnalyses>();
1521
1655
return PA;
1522
1656
}
0 commit comments