diff --git a/llvm/include/llvm/Analysis/ValueLattice.h b/llvm/include/llvm/Analysis/ValueLattice.h --- a/llvm/include/llvm/Analysis/ValueLattice.h +++ b/llvm/include/llvm/Analysis/ValueLattice.h @@ -36,6 +36,8 @@ /// as constant.) constant, + forcedconstant, + /// This Value is known to not have the specified value. (For constant /// integers, constantrange is used instead. As above, integer typed /// constantexprs can appear here.) @@ -69,6 +71,7 @@ case overdefined: case undefined: case constant: + case forcedconstant: case notconstant: break; case constantrange: @@ -105,6 +108,7 @@ Range = Other.Range; break; case constant: + case forcedconstant: case notconstant: ConstVal = Other.ConstVal; break; @@ -140,13 +144,15 @@ } bool isUndefined() const { return Tag == undefined; } - bool isConstant() const { return Tag == constant; } + bool isConstant() const { return Tag == constant || Tag == forcedconstant; } + bool isForcedConstant() const { return Tag == forcedconstant; } bool isNotConstant() const { return Tag == notconstant; } bool isConstantRange() const { return Tag == constantrange; } bool isOverdefined() const { return Tag == overdefined; } Constant *getConstant() const { - assert(isConstant() && "Cannot get the constant of a non-constant!"); + assert((isConstant() || isForcedConstant()) && + "Cannot get the constant of a non-constant!"); return ConstVal; } @@ -170,68 +176,91 @@ return None; } -private: - void markOverdefined() { + bool markOverdefined() { if (isOverdefined()) - return; + return false; if (isConstant() || isNotConstant()) ConstVal = nullptr; if (isConstantRange()) Range.~ConstantRange(); Tag = overdefined; + return true; } - void markConstant(Constant *V) { + bool markConstant(Constant *V) { + if (isa(V)) + return false; + assert(V && "Marking constant with NULL"); - if (ConstantInt *CI = dyn_cast(V)) { - markConstantRange(ConstantRange(CI->getValue())); - return; + + if (isForcedConstant() && V != getConstant()) + return markOverdefined(); + + if (isConstant()) { + assert(getConstant() == V && "Marking constant with different value"); + return false; } + + if (ConstantInt *CI = dyn_cast(V)) + return markConstantRange(ConstantRange(CI->getValue())); + + assert(isUndefined()); + Tag = constant; + ConstVal = V; + return true; + } + + bool markForcedConstant(Constant *V) { + assert(V && "Marking constant with NULL"); if (isa(V)) - return; + return false; - assert((!isConstant() || getConstant() == V) && + assert((!isForcedConstant() || getConstant() == V) && "Marking constant with different value"); assert(isUndefined()); - Tag = constant; + Tag = forcedconstant; ConstVal = V; + return true; } - void markNotConstant(Constant *V) { + bool markNotConstant(Constant *V) { assert(V && "Marking constant with NULL"); - if (ConstantInt *CI = dyn_cast(V)) { - markConstantRange(ConstantRange(CI->getValue() + 1, CI->getValue())); - return; - } + if (ConstantInt *CI = dyn_cast(V)) + return markConstantRange( + ConstantRange(CI->getValue() + 1, CI->getValue())); + if (isa(V)) - return; + return false; + + if (isNotConstant()) { + assert(getNotConstant() == V && "Marking !constant with different value"); + return false; + } - assert((!isConstant() || getConstant() != V) && - "Marking constant !constant with same value"); - assert((!isNotConstant() || getNotConstant() == V) && - "Marking !constant with different value"); - assert(isUndefined() || isConstant()); + assert(isUndefined()); Tag = notconstant; ConstVal = V; + return true; } - void markConstantRange(ConstantRange NewR) { + bool markConstantRange(ConstantRange NewR) { if (isConstantRange()) { if (NewR.isEmptySet()) markOverdefined(); else { + assert(getConstantRange().difference(NewR).isEmptySet()); Range = std::move(NewR); } - return; + return true; } assert(isUndefined()); if (NewR.isEmptySet()) - markOverdefined(); - else { - Tag = constantrange; - new (&Range) ConstantRange(std::move(NewR)); - } + return markOverdefined(); + + Tag = constantrange; + new (&Range) ConstantRange(std::move(NewR)); + return true; } public: @@ -250,6 +279,10 @@ return !RHS.isUndefined(); } + if (isForcedConstant() || RHS.isForcedConstant()) { + markOverdefined(); + return true; + } if (isConstant()) { if (RHS.isConstant() && getConstant() == RHS.getConstant()) return false; @@ -273,18 +306,16 @@ } ConstantRange NewR = getConstantRange().unionWith(RHS.getConstantRange()); if (NewR.isFullSet()) - markOverdefined(); + return markOverdefined(); else if (NewR == getConstantRange()) return false; else - markConstantRange(std::move(NewR)); - return true; + return markConstantRange(std::move(NewR)); } ConstantInt *getConstantInt() const { - assert(isConstant() && isa(getConstant()) && - "No integer constant"); - return cast(getConstant()); + assert((isConstant() || isForcedConstant()) && "No integer constant"); + return dyn_cast(getConstant()); } /// Compares this symbolic value with Other using Pred and returns either @@ -298,13 +329,22 @@ if (isConstant() && Other.isConstant()) return ConstantExpr::getCompare(Pred, getConstant(), Other.getConstant()); - // Integer constants are represented as ConstantRanges with single - // elements. - if (!isConstantRange() || !Other.isConstantRange()) + ConstantRange CR = ConstantRange::getEmpty(1); + if (isConstantRange()) + CR = getConstantRange(); + else if (isConstant() && getConstantInt()) + CR = ConstantRange(getConstantInt()->getValue()); + else + return nullptr; + + ConstantRange OtherCR = ConstantRange::getEmpty(1); + if (Other.isConstantRange()) + OtherCR = Other.getConstantRange(); + else if (Other.isConstant() && Other.getConstantInt()) + OtherCR = ConstantRange(Other.getConstantInt()->getValue()); + else return nullptr; - const auto &CR = getConstantRange(); - const auto &OtherCR = Other.getConstantRange(); if (ConstantRange::makeSatisfyingICmpRegion(Pred, OtherCR).contains(CR)) return ConstantInt::getTrue(Ty); if (ConstantRange::makeSatisfyingICmpRegion( diff --git a/llvm/lib/Analysis/ValueLattice.cpp b/llvm/lib/Analysis/ValueLattice.cpp --- a/llvm/lib/Analysis/ValueLattice.cpp +++ b/llvm/lib/Analysis/ValueLattice.cpp @@ -20,6 +20,8 @@ if (Val.isConstantRange()) return OS << "constantrange<" << Val.getConstantRange().getLower() << ", " << Val.getConstantRange().getUpper() << ">"; + if (Val.isForcedConstant()) + return OS << "forcedconstant<" << *Val.getConstant() << ">"; return OS << "constant<" << *Val.getConstant() << ">"; } } // end namespace llvm