struct ConstraintTy {
SmallVector<int64_t, 8> Coefficients;
+ SmallVector<PreconditionTy, 2> Preconditions;
- bool IsSigned;
+ bool IsSigned = false;
+ bool IsEq = false;
+
+ ConstraintTy() = default;
ConstraintTy(SmallVector<int64_t, 8> Coefficients, bool IsSigned)
: Coefficients(Coefficients), IsSigned(IsSigned) {}
unsigned size() const { return Coefficients.size(); }
-};
-
-/// Struct to manage a list of constraints with pre-conditions that must be
-/// satisfied before using the constraints.
-struct ConstraintListTy {
- SmallVector<ConstraintTy, 4> Constraints;
- SmallVector<PreconditionTy, 4> Preconditions;
-
- ConstraintListTy() = default;
-
- ConstraintListTy(ArrayRef<ConstraintTy> Constraints,
- ArrayRef<PreconditionTy> Preconditions)
- : Constraints(Constraints.begin(), Constraints.end()),
- Preconditions(Preconditions.begin(), Preconditions.end()) {}
-
- void mergeIn(const ConstraintListTy &Other) {
- append_range(Constraints, Other.Constraints);
- // TODO: Do smarter merges here, e.g. exclude duplicates.
- append_range(Preconditions, Other.Preconditions);
- }
-
- unsigned size() const { return Constraints.size(); }
- unsigned empty() const { return Constraints.empty(); }
+ unsigned empty() const { return Coefficients.empty(); }
/// Returns true if any constraint has a non-zero coefficient for any of the
/// newly added indices. Zero coefficients for new indices are removed. If it
/// returns true, no new variable need to be added to the system.
bool needsNewIndices(const DenseMap<Value *, unsigned> &NewIndices) {
- assert(size() == 1);
for (unsigned I = 0; I < NewIndices.size(); ++I) {
- int64_t Last = get(0).Coefficients.pop_back_val();
+ int64_t Last = Coefficients.pop_back_val();
if (Last != 0)
return true;
}
return false;
}
- ConstraintTy &get(unsigned I) { return Constraints[I]; }
-
/// Returns true if all preconditions for this list of constraints are
/// satisfied given \p CS and the corresponding \p Value2Index mapping.
bool isValid(const ConstraintInfo &Info) const;
/// Turn a condition \p CmpI into a vector of constraints, using indices from \p
/// Value2Index. Additional indices for newly discovered values are added to \p
/// NewIndices.
-static ConstraintListTy
+static ConstraintTy
getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
const DenseMap<Value *, unsigned> &Value2Index,
DenseMap<Value *, unsigned> &NewIndices) {
+ bool IsEq = false;
// Try to convert Pred to one of ULE/SLT/SLE/SLT.
switch (Pred) {
case CmpInst::ICMP_UGT:
if (match(Op1, m_Zero())) {
Pred = CmpInst::ICMP_ULE;
} else {
- auto A =
- getConstraint(CmpInst::ICMP_UGE, Op0, Op1, Value2Index, NewIndices);
- auto B =
- getConstraint(CmpInst::ICMP_ULE, Op0, Op1, Value2Index, NewIndices);
- A.mergeIn(B);
- return A;
+ IsEq = true;
+ Pred = CmpInst::ICMP_ULE;
}
break;
case CmpInst::ICMP_NE:
// Build result constraint, by first adding all coefficients from A and then
// subtracting all coefficients from B.
- SmallVector<int64_t, 8> R(Value2Index.size() + NewIndices.size() + 1, 0);
+ ConstraintTy Res(
+ SmallVector<int64_t, 8>(Value2Index.size() + NewIndices.size() + 1, 0),
+ IsSigned);
+ Res.IsEq = IsEq;
+ auto &R = Res.Coefficients;
for (const auto &KV : VariablesA)
R[GetOrAddIndex(KV.second)] += KV.first;
R[0] = Offset1 + Offset2 +
(Pred == (IsSigned ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT) ? -1 : 0);
- return {{{R, IsSigned}}, Preconditions};
+ Res.Preconditions = std::move(Preconditions);
+ return Res;
}
-static ConstraintListTy getConstraint(CmpInst *Cmp, ConstraintInfo &Info,
- DenseMap<Value *, unsigned> &NewIndices) {
+static ConstraintTy getConstraint(CmpInst *Cmp, ConstraintInfo &Info,
+ DenseMap<Value *, unsigned> &NewIndices) {
return getConstraint(
Cmp->getPredicate(), Cmp->getOperand(0), Cmp->getOperand(1),
Info.getValue2Index(CmpInst::isSigned(Cmp->getPredicate())), NewIndices);
}
-bool ConstraintListTy::isValid(const ConstraintInfo &Info) const {
- return all_of(Preconditions, [&Info](const PreconditionTy &C) {
- DenseMap<Value *, unsigned> NewIndices;
- auto R = getConstraint(C.Pred, C.Op0, C.Op1,
- Info.getValue2Index(CmpInst::isSigned(C.Pred)),
- NewIndices);
- // TODO: properly check NewIndices.
- return NewIndices.empty() && R.Preconditions.empty() && R.size() == 1 &&
- Info.getCS(CmpInst::isSigned(C.Pred))
- .isConditionImplied(R.get(0).Coefficients);
- });
+bool ConstraintTy::isValid(const ConstraintInfo &Info) const {
+ return Coefficients.size() > 0 &&
+ all_of(Preconditions, [&Info](const PreconditionTy &C) {
+ DenseMap<Value *, unsigned> NewIndices;
+ auto R = getConstraint(
+ C.Pred, C.Op0, C.Op1,
+ Info.getValue2Index(CmpInst::isSigned(C.Pred)), NewIndices);
+ // TODO: properly check NewIndices.
+ return NewIndices.empty() && R.Preconditions.empty() && !R.IsEq &&
+ R.size() >= 2 &&
+ Info.getCS(CmpInst::isSigned(C.Pred))
+ .isConditionImplied(R.Coefficients);
+ });
}
namespace {
DenseMap<Value *, unsigned> NewIndices;
auto R = getConstraint(Cmp, Info, NewIndices);
- if (!R.isValidSingle(Info) || R.needsNewIndices(NewIndices))
+ if (R.IsEq || R.size() < 2 || R.needsNewIndices(NewIndices) ||
+ !R.isValid(Info))
continue;
- auto &CSToUse = Info.getCS(R.get(0).IsSigned);
- if (CSToUse.isConditionImplied(R.get(0).Coefficients)) {
+ auto &CSToUse = Info.getCS(R.IsSigned);
+ if (CSToUse.isConditionImplied(R.Coefficients)) {
if (!DebugCounter::shouldExecute(EliminatedCounter))
continue;
Changed = true;
}
if (CSToUse.isConditionImplied(
- ConstraintSystem::negate(R.get(0).Coefficients))) {
+ ConstraintSystem::negate(R.Coefficients))) {
if (!DebugCounter::shouldExecute(EliminatedCounter))
continue;
LLVM_DEBUG(dbgs() << "Adding " << *CB.Condition << " " << CB.Not << "\n");
bool Added = false;
- for (auto &E : R.Constraints) {
- auto &CSToUse = Info.getCS(E.IsSigned);
- if (E.Coefficients.empty())
- continue;
+ assert(CmpInst::isSigned(CB.Condition->getPredicate()) == R.IsSigned &&
+ "condition and constraint signs must match");
+ auto &CSToUse = Info.getCS(R.IsSigned);
+ if (R.Coefficients.empty())
+ continue;
+
+ Added |= CSToUse.addVariableRowFill(R.Coefficients);
+
+ // If R has been added to the system, queue it for removal once it goes
+ // out-of-scope.
+ if (Added) {
+ for (auto &KV : NewIndices)
+ Info.getValue2Index(R.IsSigned).insert(KV);
LLVM_DEBUG({
dbgs() << " constraint: ";
- dumpWithNames(E, Info.getValue2Index(E.IsSigned));
+ dumpWithNames(R, Info.getValue2Index(R.IsSigned));
});
- Added |= CSToUse.addVariableRowFill(E.Coefficients);
+ DFSInStack.emplace_back(CB.NumIn, CB.NumOut, CB.Condition, CB.Not,
+ R.IsSigned);
+
+ if (R.IsEq) {
+ // Also add the inverted constraint for equality constraints.
+ for (auto &Coeff : R.Coefficients)
+ Coeff *= -1;
+ CSToUse.addVariableRowFill(R.Coefficients);
- // If R has been added to the system, queue it for removal once it goes
- // out-of-scope.
- if (Added)
DFSInStack.emplace_back(CB.NumIn, CB.NumOut, CB.Condition, CB.Not,
- E.IsSigned);
+ R.IsSigned);
+ }
}
}