overdefined,
};
- ValueLatticeElementTy Tag;
+ ValueLatticeElementTy Tag : 6;
+ /// Number of times a constant range has been extended with widening enabled.
+ unsigned NumRangeExtensions : 8;
/// The union either stores a pointer to a constant or a constant range,
/// associated to the lattice element. We have to ensure that Range is
new (&Range) ConstantRange(Other.Range);
else
Range = Other.Range;
+ NumRangeExtensions = Other.NumRangeExtensions;
break;
case constant:
case notconstant:
/// range or the object must be undef. The tag is set to
/// constant_range_including_undef if either the existing value or the new
/// range may include undef.
- bool markConstantRange(ConstantRange NewR, bool MayIncludeUndef = false) {
+ bool markConstantRange(ConstantRange NewR, bool MayIncludeUndef = false,
+ bool CheckWiden = false) {
if (NewR.isFullSet())
return markOverdefined();
if (getConstantRange() == NewR)
return Tag != OldTag;
+ // Simple form of widening. If a range is extended multiple times, go to
+ // overdefined.
+ if (CheckWiden && ++NumRangeExtensions == 1)
+ return markOverdefined();
+
assert(NewR.contains(getConstantRange()) &&
"Existing range must be a subset of NewR");
Range = std::move(NewR);
if (NewR.isEmptySet())
return markOverdefined();
+ NumRangeExtensions = 0;
Tag = NewTag;
new (&Range) ConstantRange(std::move(NewR));
return true;
/// Updates this object to approximate both this object and RHS. Returns
/// true if this object has been changed.
- bool mergeIn(const ValueLatticeElement &RHS) {
+ bool mergeIn(const ValueLatticeElement &RHS, bool CheckWiden = false) {
if (RHS.isUnknown() || isOverdefined())
return false;
if (RHS.isOverdefined()) {
return markConstant(RHS.getConstant(), /*MayIncludeUndef=*/true);
if (RHS.isConstantRange())
return markConstantRange(RHS.getConstantRange(true),
- /*MayIncludeUndef=*/true);
+ /*MayIncludeUndef=*/true, CheckWiden);
return markOverdefined();
}
ConstantRange NewR = getConstantRange().unionWith(RHS.getConstantRange());
return markConstantRange(
std::move(NewR),
- /*MayIncludeUndef=*/RHS.isConstantRangeIncludingUndef());
+ /*MayIncludeUndef=*/RHS.isConstantRangeIncludingUndef(), CheckWiden);
}
// Compares this symbolic value with Other using Pred and returns either
}
};
-raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val);
+static_assert(sizeof(ValueLatticeElement) <= 40,
+ "size of ValueLatticeElement changed unexpectedly");
+raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val);
} // end namespace llvm
#endif
bool mergeInValue(ValueLatticeElement &IV, Value *V,
ValueLatticeElement MergeWithV, bool Widen = true) {
- // Do a simple form of widening, to avoid extending a range repeatedly in a
- // loop. If IV is a constant range, it means we already set it once. If
- // MergeWithV would extend IV, mark V as overdefined.
- if (Widen && IV.isConstantRange() && MergeWithV.isConstantRange() &&
- !IV.getConstantRange().contains(MergeWithV.getConstantRange())) {
- markOverdefined(IV, V);
- return true;
- }
- if (IV.mergeIn(MergeWithV)) {
+ if (IV.mergeIn(MergeWithV, Widen)) {
pushToWorkList(IV, V);
LLVM_DEBUG(dbgs() << "Merged " << MergeWithV << " into " << *V << " : "
<< IV << "\n");