unsigned size() const { return Coefficients.size(); }
};
-/// Turn a condition \p CmpI into a constraint vector, using indices from \p
-/// Value2Index. If \p ShouldAdd is true, new indices are added for values not
-/// yet in \p Value2Index.
+/// 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 SmallVector<ConstraintTy, 4>
getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
- DenseMap<Value *, unsigned> &Value2Index, bool ShouldAdd) {
+ const DenseMap<Value *, unsigned> &Value2Index,
+ DenseMap<Value *, unsigned> &NewIndices) {
int64_t Offset1 = 0;
int64_t Offset2 = 0;
- auto TryToGetIndex = [ShouldAdd,
- &Value2Index](Value *V) -> Optional<unsigned> {
- if (ShouldAdd) {
- Value2Index.insert({V, Value2Index.size() + 1});
- return Value2Index[V];
- }
- auto I = Value2Index.find(V);
- if (I == Value2Index.end())
- return None;
- return I->second;
+ // First try to look up \p V in Value2Index and NewIndices. Otherwise add a
+ // new entry to NewIndices.
+ auto GetOrAddIndex = [&Value2Index, &NewIndices](Value *V) -> unsigned {
+ auto V2I = Value2Index.find(V);
+ if (V2I != Value2Index.end())
+ return V2I->second;
+ auto NewI = NewIndices.find(V);
+ if (NewI != NewIndices.end())
+ return NewI->second;
+ auto Insert =
+ NewIndices.insert({V, Value2Index.size() + NewIndices.size() + 1});
+ return Insert.first->second;
};
if (Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE)
return getConstraint(CmpInst::getSwappedPredicate(Pred), Op1, Op0,
- Value2Index, ShouldAdd);
+ Value2Index, NewIndices);
if (Pred == CmpInst::ICMP_EQ) {
- auto A = getConstraint(CmpInst::ICMP_UGE, Op0, Op1, Value2Index, ShouldAdd);
- auto B = getConstraint(CmpInst::ICMP_ULE, Op0, Op1, Value2Index, ShouldAdd);
+ auto A =
+ getConstraint(CmpInst::ICMP_UGE, Op0, Op1, Value2Index, NewIndices);
+ auto B =
+ getConstraint(CmpInst::ICMP_ULE, Op0, Op1, Value2Index, NewIndices);
append_range(A, B);
return A;
}
auto VariablesA = make_range(std::next(ADec.begin()), ADec.end());
auto VariablesB = make_range(std::next(BDec.begin()), BDec.end());
- // Check if each referenced value in the constraint is already in the system
- // or can be added (if ShouldAdd is true).
+ // Make sure all variables have entries in Value2Index or NewIndices.
for (const auto &KV :
concat<std::pair<int64_t, Value *>>(VariablesA, VariablesB))
- if (!TryToGetIndex(KV.second))
- return {};
+ GetOrAddIndex(KV.second);
// Build result constraint, by first adding all coefficients from A and then
// subtracting all coefficients from B.
- SmallVector<int64_t, 8> R(Value2Index.size() + 1, 0);
+ SmallVector<int64_t, 8> R(Value2Index.size() + NewIndices.size() + 1, 0);
for (const auto &KV : VariablesA)
- R[Value2Index[KV.second]] += KV.first;
+ R[GetOrAddIndex(KV.second)] += KV.first;
for (const auto &KV : VariablesB)
- R[Value2Index[KV.second]] -= KV.first;
+ R[GetOrAddIndex(KV.second)] -= KV.first;
R[0] = Offset1 + Offset2 + (Pred == CmpInst::ICMP_ULT ? -1 : 0);
return {R};
}
static SmallVector<ConstraintTy, 4>
-getConstraint(CmpInst *Cmp, DenseMap<Value *, unsigned> &Value2Index,
- bool ShouldAdd) {
+getConstraint(CmpInst *Cmp, const DenseMap<Value *, unsigned> &Value2Index,
+ DenseMap<Value *, unsigned> &NewIndices) {
return getConstraint(Cmp->getPredicate(), Cmp->getOperand(0),
- Cmp->getOperand(1), Value2Index, ShouldAdd);
+ Cmp->getOperand(1), Value2Index, NewIndices);
}
namespace {
auto *Cmp = dyn_cast<CmpInst>(&I);
if (!Cmp)
continue;
- auto R = getConstraint(Cmp, Value2Index, false);
- if (R.size() != 1 || R[0].size() == 1)
+
+ DenseMap<Value *, unsigned> NewIndices;
+ auto R = getConstraint(Cmp, Value2Index, NewIndices);
+ if (R.size() != 1)
+ continue;
+
+ // Check if all coefficients of new indices are 0 after building the
+ // constraint. Skip if any of the new indices has a non-null
+ // coefficient.
+ bool HasNewIndex = false;
+ for (unsigned I = 0; I < NewIndices.size(); ++I) {
+ int64_t Last = R[0].Coefficients.pop_back_val();
+ if (Last != 0) {
+ HasNewIndex = true;
+ break;
+ }
+ }
+ if (HasNewIndex || R[0].size() == 1)
continue;
+
if (CS.isConditionImplied(R[0].Coefficients)) {
if (!DebugCounter::shouldExecute(EliminatedCounter))
continue;
// Otherwise, add the condition to the system and stack, if we can transform
// it into a constraint.
- auto R = getConstraint(CB.Condition, Value2Index, true);
+ DenseMap<Value *, unsigned> NewIndices;
+ auto R = getConstraint(CB.Condition, Value2Index, NewIndices);
if (R.empty())
continue;
+ for (auto &KV : NewIndices)
+ Value2Index.insert(KV);
+
LLVM_DEBUG(dbgs() << "Adding " << *CB.Condition << " " << CB.Not << "\n");
bool Added = false;
for (auto &C : R) {
; CHECK-NEXT: br i1 [[CMP_PRE]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK: if.then:
; CHECK-NEXT: [[T_0:%.*]] = icmp ult i8 [[START_ADD_IDX]], [[START_ADD_N]]
-; CHECK-NEXT: call void @use(i1 [[T_0]])
+; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[F_0:%.*]] = icmp uge i8 [[START_ADD_IDX]], [[START_ADD_N]]
-; CHECK-NEXT: call void @use(i1 [[F_0]])
+; CHECK-NEXT: call void @use(i1 false)
; CHECK-NEXT: [[C_1:%.*]] = icmp ult i8 [[START_ADD_1]], [[START_ADD_N]]
; CHECK-NEXT: call void @use(i1 [[C_1]])
; CHECK-NEXT: [[C_2:%.*]] = icmp ult i8 [[START_ADD_IDX]], [[START_ADD_1]]
; CHECK-NEXT: ret void
; CHECK: if.end:
; CHECK-NEXT: [[F_1:%.*]] = icmp ult i8 [[START_ADD_IDX]], [[START_ADD_N]]
-; CHECK-NEXT: call void @use(i1 [[F_1]])
+; CHECK-NEXT: call void @use(i1 false)
; CHECK-NEXT: [[T_1:%.*]] = icmp uge i8 [[START_ADD_IDX]], [[START_ADD_N]]
-; CHECK-NEXT: call void @use(i1 [[T_1]])
+; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[C_3:%.*]] = icmp ult i8 [[START_ADD_1]], [[START_ADD_N]]
; CHECK-NEXT: call void @use(i1 [[C_3]])
; CHECK-NEXT: [[C_4:%.*]] = icmp ult i8 [[START_ADD_IDX]], [[START_ADD_1]]