@@ -83,6 +83,16 @@ static Instruction *getContextInstForUse(Use &U) {
83
83
}
84
84
85
85
namespace {
86
+ // / Struct to express a condition of the form %Op0 Pred %Op1.
87
+ struct ConditionTy {
88
+ CmpInst::Predicate Pred;
89
+ Value *Op0;
90
+ Value *Op1;
91
+
92
+ ConditionTy (CmpInst::Predicate Pred, Value *Op0, Value *Op1)
93
+ : Pred(Pred), Op0(Op0), Op1(Op1) {}
94
+ };
95
+
86
96
// / Represents either
87
97
// / * a condition that holds on entry to a block (=condition fact)
88
98
// / * an assume (=assume fact)
@@ -101,37 +111,45 @@ struct FactOrCheck {
101
111
union {
102
112
Instruction *Inst;
103
113
Use *U;
114
+ ConditionTy Cond;
104
115
};
105
116
106
117
unsigned NumIn;
107
118
unsigned NumOut;
108
119
EntryTy Ty;
109
- bool Not;
110
120
111
- FactOrCheck (EntryTy Ty, DomTreeNode *DTN, Instruction *Inst, bool Not )
121
+ FactOrCheck (EntryTy Ty, DomTreeNode *DTN, Instruction *Inst)
112
122
: Inst(Inst), NumIn(DTN->getDFSNumIn ()), NumOut(DTN->getDFSNumOut ()),
113
- Ty(Ty), Not(Not) {}
123
+ Ty(Ty) {}
114
124
115
125
FactOrCheck (DomTreeNode *DTN, Use *U)
116
126
: U(U), NumIn(DTN->getDFSNumIn ()), NumOut(DTN->getDFSNumOut ()),
117
- Ty(EntryTy::UseCheck), Not( false ) {}
127
+ Ty(EntryTy::UseCheck) {}
118
128
119
- static FactOrCheck getConditionFact (DomTreeNode *DTN, CmpInst *Inst,
120
- bool Not = false ) {
121
- return FactOrCheck (EntryTy::ConditionFact, DTN, Inst, Not);
129
+ FactOrCheck (DomTreeNode *DTN, CmpInst::Predicate Pred, Value *Op0, Value *Op1)
130
+ : Cond(Pred, Op0, Op1), NumIn(DTN->getDFSNumIn ()),
131
+ NumOut(DTN->getDFSNumOut ()), Ty(EntryTy::ConditionFact) {}
132
+
133
+ static FactOrCheck getConditionFact (DomTreeNode *DTN, CmpInst::Predicate Pred,
134
+ Value *Op0, Value *Op1) {
135
+ return FactOrCheck (DTN, Pred, Op0, Op1);
136
+ }
137
+
138
+ static FactOrCheck getInstFact (DomTreeNode *DTN, Instruction *Inst) {
139
+ return FactOrCheck (EntryTy::InstFact, DTN, Inst);
122
140
}
123
141
124
- static FactOrCheck getInstFact (DomTreeNode *DTN, Instruction *Inst ,
125
- bool Not = false ) {
126
- return FactOrCheck (EntryTy::InstFact, DTN, Inst, Not );
142
+ static FactOrCheck getFact (DomTreeNode *DTN, CmpInst::Predicate Pred ,
143
+ Value *Op0, Value *Op1 ) {
144
+ return FactOrCheck (DTN, Pred, Op0, Op1 );
127
145
}
128
146
129
147
static FactOrCheck getCheck (DomTreeNode *DTN, Use *U) {
130
148
return FactOrCheck (DTN, U);
131
149
}
132
150
133
151
static FactOrCheck getCheck (DomTreeNode *DTN, CallInst *CI) {
134
- return FactOrCheck (EntryTy::InstCheck, DTN, CI, false );
152
+ return FactOrCheck (EntryTy::InstCheck, DTN, CI);
135
153
}
136
154
137
155
bool isCheck () const {
@@ -188,19 +206,9 @@ struct StackEntry {
188
206
ValuesToRelease (ValuesToRelease) {}
189
207
};
190
208
191
- // / Struct to express a pre-condition of the form %Op0 Pred %Op1.
192
- struct PreconditionTy {
193
- CmpInst::Predicate Pred;
194
- Value *Op0;
195
- Value *Op1;
196
-
197
- PreconditionTy (CmpInst::Predicate Pred, Value *Op0, Value *Op1)
198
- : Pred(Pred), Op0(Op0), Op1(Op1) {}
199
- };
200
-
201
209
struct ConstraintTy {
202
210
SmallVector<int64_t , 8 > Coefficients;
203
- SmallVector<PreconditionTy , 2 > Preconditions;
211
+ SmallVector<ConditionTy , 2 > Preconditions;
204
212
205
213
SmallVector<SmallVector<int64_t , 8 >> ExtraInfo;
206
214
@@ -346,17 +354,17 @@ struct Decomposition {
346
354
} // namespace
347
355
348
356
static Decomposition decompose (Value *V,
349
- SmallVectorImpl<PreconditionTy > &Preconditions,
357
+ SmallVectorImpl<ConditionTy > &Preconditions,
350
358
bool IsSigned, const DataLayout &DL);
351
359
352
360
static bool canUseSExt (ConstantInt *CI) {
353
361
const APInt &Val = CI->getValue ();
354
362
return Val.sgt (MinSignedConstraintValue) && Val.slt (MaxConstraintValue);
355
363
}
356
364
357
- static Decomposition
358
- decomposeGEP (GEPOperator &GEP, SmallVectorImpl<PreconditionTy > &Preconditions,
359
- bool IsSigned, const DataLayout &DL) {
365
+ static Decomposition decomposeGEP (GEPOperator &GEP,
366
+ SmallVectorImpl<ConditionTy > &Preconditions,
367
+ bool IsSigned, const DataLayout &DL) {
360
368
// Do not reason about pointers where the index size is larger than 64 bits,
361
369
// as the coefficients used to encode constraints are 64 bit integers.
362
370
if (DL.getIndexTypeSizeInBits (GEP.getPointerOperand ()->getType ()) > 64 )
@@ -417,7 +425,7 @@ decomposeGEP(GEPOperator &GEP, SmallVectorImpl<PreconditionTy> &Preconditions,
417
425
// Variable } where Coefficient * Variable. The sum of the constant offset and
418
426
// pairs equals \p V.
419
427
static Decomposition decompose (Value *V,
420
- SmallVectorImpl<PreconditionTy > &Preconditions,
428
+ SmallVectorImpl<ConditionTy > &Preconditions,
421
429
bool IsSigned, const DataLayout &DL) {
422
430
423
431
auto MergeResults = [&Preconditions, IsSigned, &DL](Value *A, Value *B,
@@ -560,7 +568,7 @@ ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
560
568
Pred != CmpInst::ICMP_SLE && Pred != CmpInst::ICMP_SLT)
561
569
return {};
562
570
563
- SmallVector<PreconditionTy , 4 > Preconditions;
571
+ SmallVector<ConditionTy , 4 > Preconditions;
564
572
bool IsSigned = CmpInst::isSigned (Pred);
565
573
auto &Value2Index = getValue2Index (IsSigned);
566
574
auto ADec = decompose (Op0->stripPointerCastsSameRepresentation (),
@@ -670,7 +678,7 @@ ConstraintTy ConstraintInfo::getConstraintForSolving(CmpInst::Predicate Pred,
670
678
671
679
bool ConstraintTy::isValid (const ConstraintInfo &Info) const {
672
680
return Coefficients.size () > 0 &&
673
- all_of (Preconditions, [&Info](const PreconditionTy &C) {
681
+ all_of (Preconditions, [&Info](const ConditionTy &C) {
674
682
return Info.doesHold (C.Pred , C.Op0 , C.Op1 );
675
683
});
676
684
}
@@ -805,15 +813,16 @@ void State::addInfoFor(BasicBlock &BB) {
805
813
continue ;
806
814
}
807
815
808
- Value *Cond;
816
+ Value *A, *B;
817
+ CmpInst::Predicate Pred;
809
818
// For now, just handle assumes with a single compare as condition.
810
- if (match (&I, m_Intrinsic<Intrinsic::assume>(m_Value (Cond))) &&
811
- isa<ICmpInst>(Cond )) {
819
+ if (match (&I, m_Intrinsic<Intrinsic::assume>(
820
+ m_ICmp (Pred, m_Value (A), m_Value (B))) )) {
812
821
if (GuaranteedToExecute) {
813
822
// The assume is guaranteed to execute when BB is entered, hence Cond
814
823
// holds on entry to BB.
815
824
WorkList.emplace_back (FactOrCheck::getConditionFact (
816
- DT.getNode (I.getParent ()), cast<CmpInst>(Cond) ));
825
+ DT.getNode (I.getParent ()), Pred, A, B ));
817
826
} else {
818
827
WorkList.emplace_back (
819
828
FactOrCheck::getInstFact (DT.getNode (I.getParent ()), &I));
@@ -853,8 +862,11 @@ void State::addInfoFor(BasicBlock &BB) {
853
862
while (!CondWorkList.empty ()) {
854
863
Value *Cur = CondWorkList.pop_back_val ();
855
864
if (auto *Cmp = dyn_cast<ICmpInst>(Cur)) {
856
- WorkList.emplace_back (
857
- FactOrCheck::getConditionFact (DT.getNode (Successor), Cmp, IsOr));
865
+ WorkList.emplace_back (FactOrCheck::getConditionFact (
866
+ DT.getNode (Successor),
867
+ IsOr ? CmpInst::getInversePredicate (Cmp->getPredicate ())
868
+ : Cmp->getPredicate (),
869
+ Cmp->getOperand (0 ), Cmp->getOperand (1 )));
858
870
continue ;
859
871
}
860
872
if (IsOr && match (Cur, m_LogicalOr (m_Value (Op0), m_Value (Op1)))) {
@@ -876,11 +888,14 @@ void State::addInfoFor(BasicBlock &BB) {
876
888
if (!CmpI)
877
889
return ;
878
890
if (canAddSuccessor (BB, Br->getSuccessor (0 )))
879
- WorkList.emplace_back (
880
- FactOrCheck::getConditionFact (DT.getNode (Br->getSuccessor (0 )), CmpI));
891
+ WorkList.emplace_back (FactOrCheck::getConditionFact (
892
+ DT.getNode (Br->getSuccessor (0 )), CmpI->getPredicate (),
893
+ CmpI->getOperand (0 ), CmpI->getOperand (1 )));
881
894
if (canAddSuccessor (BB, Br->getSuccessor (1 )))
882
895
WorkList.emplace_back (FactOrCheck::getConditionFact (
883
- DT.getNode (Br->getSuccessor (1 )), CmpI, true ));
896
+ DT.getNode (Br->getSuccessor (1 )),
897
+ CmpInst::getInversePredicate (CmpI->getPredicate ()), CmpI->getOperand (0 ),
898
+ CmpI->getOperand (1 )));
884
899
}
885
900
886
901
namespace {
@@ -1312,8 +1327,9 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT,
1312
1327
// transfer logic.
1313
1328
stable_sort (S.WorkList , [](const FactOrCheck &A, const FactOrCheck &B) {
1314
1329
auto HasNoConstOp = [](const FactOrCheck &B) {
1315
- return !isa<ConstantInt>(B.Inst ->getOperand (0 )) &&
1316
- !isa<ConstantInt>(B.Inst ->getOperand (1 ));
1330
+ Value *V0 = B.isConditionFact () ? B.Cond .Op0 : B.Inst ->getOperand (0 );
1331
+ Value *V1 = B.isConditionFact () ? B.Cond .Op1 : B.Inst ->getOperand (1 );
1332
+ return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
1317
1333
};
1318
1334
// If both entries have the same In numbers, conditional facts come first.
1319
1335
// Otherwise use the relative order in the basic block.
@@ -1386,7 +1402,6 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT,
1386
1402
continue ;
1387
1403
}
1388
1404
1389
- LLVM_DEBUG (dbgs () << " fact to add to the system: " << *CB.Inst << " \n " );
1390
1405
auto AddFact = [&](CmpInst::Predicate Pred, Value *A, Value *B) {
1391
1406
if (Info.getCS (CmpInst::isSigned (Pred)).size () > MaxRows) {
1392
1407
LLVM_DEBUG (
@@ -1395,6 +1410,14 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT,
1395
1410
return ;
1396
1411
}
1397
1412
1413
+ LLVM_DEBUG ({
1414
+ dbgs () << " Processing fact to add to the system: " << Pred << " " ;
1415
+ A->printAsOperand (dbgs ());
1416
+ dbgs () << " , " ;
1417
+ B->printAsOperand (dbgs (), false );
1418
+ dbgs () << " \n " ;
1419
+ });
1420
+
1398
1421
Info.addFact (Pred, A, B, CB.NumIn , CB.NumOut , DFSInStack);
1399
1422
if (ReproducerModule && DFSInStack.size () > ReproducerCondStack.size ())
1400
1423
ReproducerCondStack.emplace_back (Pred, A, B);
@@ -1413,23 +1436,27 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT,
1413
1436
};
1414
1437
1415
1438
ICmpInst::Predicate Pred;
1416
- if (auto *MinMax = dyn_cast<MinMaxIntrinsic>(CB.Inst )) {
1417
- Pred = ICmpInst::getNonStrictPredicate (MinMax->getPredicate ());
1418
- AddFact (Pred, MinMax, MinMax->getLHS ());
1419
- AddFact (Pred, MinMax, MinMax->getRHS ());
1420
- continue ;
1439
+ if (!CB.isConditionFact ()) {
1440
+ if (auto *MinMax = dyn_cast<MinMaxIntrinsic>(CB.Inst )) {
1441
+ Pred = ICmpInst::getNonStrictPredicate (MinMax->getPredicate ());
1442
+ AddFact (Pred, MinMax, MinMax->getLHS ());
1443
+ AddFact (Pred, MinMax, MinMax->getRHS ());
1444
+ continue ;
1445
+ }
1421
1446
}
1422
1447
1423
- Value *A, *B;
1424
- Value *Cmp = CB.Inst ;
1425
- match (Cmp, m_Intrinsic<Intrinsic::assume>(m_Value (Cmp)));
1426
- if (match (Cmp, m_ICmp (Pred, m_Value (A), m_Value (B)))) {
1427
- // Use the inverse predicate if required.
1428
- if (CB.Not )
1429
- Pred = CmpInst::getInversePredicate (Pred);
1430
-
1431
- AddFact (Pred, A, B);
1448
+ Value *A = nullptr , *B = nullptr ;
1449
+ if (CB.isConditionFact ()) {
1450
+ Pred = CB.Cond .Pred ;
1451
+ A = CB.Cond .Op0 ;
1452
+ B = CB.Cond .Op1 ;
1453
+ } else {
1454
+ bool Matched = match (CB.Inst , m_Intrinsic<Intrinsic::assume>(
1455
+ m_ICmp (Pred, m_Value (A), m_Value (B))));
1456
+ (void )Matched;
1457
+ assert (Matched && " Must have an assume intrinsic with a icmp operand" );
1432
1458
}
1459
+ AddFact (Pred, A, B);
1433
1460
}
1434
1461
1435
1462
if (ReproducerModule && !ReproducerModule->functions ().empty ()) {
0 commit comments