summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Analysis/LazyValueInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Analysis/LazyValueInfo.cpp')
-rw-r--r--contrib/llvm/lib/Analysis/LazyValueInfo.cpp707
1 files changed, 499 insertions, 208 deletions
diff --git a/contrib/llvm/lib/Analysis/LazyValueInfo.cpp b/contrib/llvm/lib/Analysis/LazyValueInfo.cpp
index 961c010..3ce667f 100644
--- a/contrib/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/contrib/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -38,18 +38,19 @@ using namespace PatternMatch;
#define DEBUG_TYPE "lazy-value-info"
-char LazyValueInfo::ID = 0;
-INITIALIZE_PASS_BEGIN(LazyValueInfo, "lazy-value-info",
+char LazyValueInfoWrapperPass::ID = 0;
+INITIALIZE_PASS_BEGIN(LazyValueInfoWrapperPass, "lazy-value-info",
"Lazy Value Information Analysis", false, true)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
-INITIALIZE_PASS_END(LazyValueInfo, "lazy-value-info",
+INITIALIZE_PASS_END(LazyValueInfoWrapperPass, "lazy-value-info",
"Lazy Value Information Analysis", false, true)
namespace llvm {
- FunctionPass *createLazyValueInfoPass() { return new LazyValueInfo(); }
+ FunctionPass *createLazyValueInfoPass() { return new LazyValueInfoWrapperPass(); }
}
+char LazyValueAnalysis::PassID;
//===----------------------------------------------------------------------===//
// LVILatticeVal
@@ -63,19 +64,24 @@ namespace llvm {
namespace {
class LVILatticeVal {
enum LatticeValueTy {
- /// This Value has no known value yet.
+ /// This Value has no known value yet. As a result, this implies the
+ /// producing instruction is dead. Caution: We use this as the starting
+ /// state in our local meet rules. In this usage, it's taken to mean
+ /// "nothing known yet".
undefined,
- /// This Value has a specific constant value.
+ /// This Value has a specific constant value. (For integers, constantrange
+ /// is used instead.)
constant,
- /// This Value is known to not have the specified value.
+ /// This Value is known to not have the specified value. (For integers,
+ /// constantrange is used instead.)
notconstant,
- /// The Value falls within this range.
+ /// The Value falls within this range. (Used only for integer typed values.)
constantrange,
- /// This value is not known to be constant, and we know that it has a value.
+ /// We can not precisely model the dynamic values this value might take.
overdefined
};
@@ -102,7 +108,7 @@ public:
}
static LVILatticeVal getRange(ConstantRange CR) {
LVILatticeVal Res;
- Res.markConstantRange(CR);
+ Res.markConstantRange(std::move(CR));
return Res;
}
static LVILatticeVal getOverdefined() {
@@ -110,7 +116,7 @@ public:
Res.markOverdefined();
return Res;
}
-
+
bool isUndefined() const { return Tag == undefined; }
bool isConstant() const { return Tag == constant; }
bool isNotConstant() const { return Tag == notconstant; }
@@ -176,13 +182,13 @@ public:
}
/// Return true if this is a change in status.
- bool markConstantRange(const ConstantRange NewR) {
+ bool markConstantRange(ConstantRange NewR) {
if (isConstantRange()) {
if (NewR.isEmptySet())
return markOverdefined();
bool changed = Range != NewR;
- Range = NewR;
+ Range = std::move(NewR);
return changed;
}
@@ -191,7 +197,7 @@ public:
return markOverdefined();
Tag = constantrange;
- Range = NewR;
+ Range = std::move(NewR);
return true;
}
@@ -230,11 +236,6 @@ public:
return markOverdefined();
}
- // RHS is a ConstantRange, LHS is a non-integer Constant.
-
- // FIXME: consider the case where RHS is a range [1, 0) and LHS is
- // a function. The correct result is to pick up RHS.
-
return markOverdefined();
}
@@ -287,13 +288,76 @@ raw_ostream &operator<<(raw_ostream &OS, const LVILatticeVal &Val) {
if (Val.isNotConstant())
return OS << "notconstant<" << *Val.getNotConstant() << '>';
- else if (Val.isConstantRange())
+ if (Val.isConstantRange())
return OS << "constantrange<" << Val.getConstantRange().getLower() << ", "
<< Val.getConstantRange().getUpper() << '>';
return OS << "constant<" << *Val.getConstant() << '>';
}
}
+/// Returns true if this lattice value represents at most one possible value.
+/// This is as precise as any lattice value can get while still representing
+/// reachable code.
+static bool hasSingleValue(const LVILatticeVal &Val) {
+ if (Val.isConstantRange() &&
+ Val.getConstantRange().isSingleElement())
+ // Integer constants are single element ranges
+ return true;
+ if (Val.isConstant())
+ // Non integer constants
+ return true;
+ return false;
+}
+
+/// Combine two sets of facts about the same value into a single set of
+/// facts. Note that this method is not suitable for merging facts along
+/// different paths in a CFG; that's what the mergeIn function is for. This
+/// is for merging facts gathered about the same value at the same location
+/// through two independent means.
+/// Notes:
+/// * This method does not promise to return the most precise possible lattice
+/// value implied by A and B. It is allowed to return any lattice element
+/// which is at least as strong as *either* A or B (unless our facts
+/// conflict, see below).
+/// * Due to unreachable code, the intersection of two lattice values could be
+/// contradictory. If this happens, we return some valid lattice value so as
+/// not confuse the rest of LVI. Ideally, we'd always return Undefined, but
+/// we do not make this guarantee. TODO: This would be a useful enhancement.
+static LVILatticeVal intersect(LVILatticeVal A, LVILatticeVal B) {
+ // Undefined is the strongest state. It means the value is known to be along
+ // an unreachable path.
+ if (A.isUndefined())
+ return A;
+ if (B.isUndefined())
+ return B;
+
+ // If we gave up for one, but got a useable fact from the other, use it.
+ if (A.isOverdefined())
+ return B;
+ if (B.isOverdefined())
+ return A;
+
+ // Can't get any more precise than constants.
+ if (hasSingleValue(A))
+ return A;
+ if (hasSingleValue(B))
+ return B;
+
+ // Could be either constant range or not constant here.
+ if (!A.isConstantRange() || !B.isConstantRange()) {
+ // TODO: Arbitrary choice, could be improved
+ return A;
+ }
+
+ // Intersect two constant ranges
+ ConstantRange Range =
+ A.getConstantRange().intersectWith(B.getConstantRange());
+ // Note: An empty range is implicitly converted to overdefined internally.
+ // TODO: We could instead use Undefined here since we've proven a conflict
+ // and thus know this path must be unreachable.
+ return LVILatticeVal::getRange(std::move(Range));
+}
+
//===----------------------------------------------------------------------===//
// LazyValueInfoCache Decl
//===----------------------------------------------------------------------===//
@@ -354,6 +418,8 @@ namespace {
if (!BlockValueSet.insert(BV).second)
return false; // It's already in the stack.
+ DEBUG(dbgs() << "PUSH: " << *BV.second << " in " << BV.first->getName()
+ << "\n");
BlockValueStack.push(BV);
return true;
}
@@ -375,30 +441,31 @@ namespace {
lookup(Val)[BB] = Result;
}
- LVILatticeVal getBlockValue(Value *Val, BasicBlock *BB);
- bool getEdgeValue(Value *V, BasicBlock *F, BasicBlock *T,
- LVILatticeVal &Result,
- Instruction *CxtI = nullptr);
- bool hasBlockValue(Value *Val, BasicBlock *BB);
-
- // These methods process one work item and may add more. A false value
- // returned means that the work item was not completely processed and must
- // be revisited after going through the new items.
- bool solveBlockValue(Value *Val, BasicBlock *BB);
- bool solveBlockValueNonLocal(LVILatticeVal &BBLV,
- Value *Val, BasicBlock *BB);
- bool solveBlockValuePHINode(LVILatticeVal &BBLV,
- PHINode *PN, BasicBlock *BB);
- bool solveBlockValueConstantRange(LVILatticeVal &BBLV,
- Instruction *BBI, BasicBlock *BB);
- void mergeAssumeBlockValueConstantRange(Value *Val, LVILatticeVal &BBLV,
- Instruction *BBI);
-
- void solve();
-
- ValueCacheEntryTy &lookup(Value *V) {
- return ValueCache[LVIValueHandle(V, this)];
- }
+ LVILatticeVal getBlockValue(Value *Val, BasicBlock *BB);
+ bool getEdgeValue(Value *V, BasicBlock *F, BasicBlock *T,
+ LVILatticeVal &Result, Instruction *CxtI = nullptr);
+ bool hasBlockValue(Value *Val, BasicBlock *BB);
+
+ // These methods process one work item and may add more. A false value
+ // returned means that the work item was not completely processed and must
+ // be revisited after going through the new items.
+ bool solveBlockValue(Value *Val, BasicBlock *BB);
+ bool solveBlockValueNonLocal(LVILatticeVal &BBLV, Value *Val, BasicBlock *BB);
+ bool solveBlockValuePHINode(LVILatticeVal &BBLV, PHINode *PN, BasicBlock *BB);
+ bool solveBlockValueSelect(LVILatticeVal &BBLV, SelectInst *S,
+ BasicBlock *BB);
+ bool solveBlockValueBinaryOp(LVILatticeVal &BBLV, Instruction *BBI,
+ BasicBlock *BB);
+ bool solveBlockValueCast(LVILatticeVal &BBLV, Instruction *BBI,
+ BasicBlock *BB);
+ void intersectAssumeBlockValueConstantRange(Value *Val, LVILatticeVal &BBLV,
+ Instruction *BBI);
+
+ void solve();
+
+ ValueCacheEntryTy &lookup(Value *V) {
+ return ValueCache[LVIValueHandle(V, this)];
+ }
bool isOverdefined(Value *V, BasicBlock *BB) const {
auto ODI = OverDefinedCache.find(BB);
@@ -427,7 +494,7 @@ namespace {
return lookup(V)[BB];
}
-
+
public:
/// This is the query interface to determine the lattice
/// value for the specified Value* at the end of the specified block.
@@ -493,8 +560,8 @@ void LazyValueInfoCache::eraseBlock(BasicBlock *BB) {
if (ODI != OverDefinedCache.end())
OverDefinedCache.erase(ODI);
- for (auto I = ValueCache.begin(), E = ValueCache.end(); I != E; ++I)
- I->second.erase(BB);
+ for (auto &I : ValueCache)
+ I.second.erase(BB);
}
void LazyValueInfoCache::solve() {
@@ -508,6 +575,9 @@ void LazyValueInfoCache::solve() {
assert(hasCachedValueInfo(e.second, e.first) &&
"Result should be in cache!");
+ DEBUG(dbgs() << "POP " << *e.second << " in " << e.first->getName()
+ << " = " << getCachedValueInfo(e.second, e.first) << "\n");
+
BlockValueStack.pop();
BlockValueSet.erase(e);
} else {
@@ -542,15 +612,12 @@ static LVILatticeVal getFromRangeMetadata(Instruction *BBI) {
case Instruction::Invoke:
if (MDNode *Ranges = BBI->getMetadata(LLVMContext::MD_range))
if (isa<IntegerType>(BBI->getType())) {
- ConstantRange Result = getConstantRangeFromMetadata(*Ranges);
- return LVILatticeVal::getRange(Result);
+ return LVILatticeVal::getRange(getConstantRangeFromMetadata(*Ranges));
}
break;
};
- // Nothing known - Note that we do not want overdefined here. We may know
- // something else about the value and not having range metadata shouldn't
- // cause us to throw away those facts.
- return LVILatticeVal();
+ // Nothing known - will be intersected with other facts
+ return LVILatticeVal::getOverdefined();
}
bool LazyValueInfoCache::solveBlockValue(Value *Val, BasicBlock *BB) {
@@ -587,44 +654,47 @@ bool LazyValueInfoCache::solveBlockValue(Value *Val, BasicBlock *BB) {
return true;
}
- // If this value is a nonnull pointer, record it's range and bailout.
- PointerType *PT = dyn_cast<PointerType>(BBI->getType());
- if (PT && isKnownNonNull(BBI)) {
- Res = LVILatticeVal::getNot(ConstantPointerNull::get(PT));
+ if (auto *SI = dyn_cast<SelectInst>(BBI)) {
+ if (!solveBlockValueSelect(Res, SI, BB))
+ return false;
insertResult(Val, BB, Res);
return true;
}
- // If this is an instruction which supports range metadata, return the
- // implied range. TODO: This should be an intersection, not a union.
- Res.mergeIn(getFromRangeMetadata(BBI), DL);
-
- // We can only analyze the definitions of certain classes of instructions
- // (integral binops and casts at the moment), so bail if this isn't one.
- LVILatticeVal Result;
- if ((!isa<BinaryOperator>(BBI) && !isa<CastInst>(BBI)) ||
- !BBI->getType()->isIntegerTy()) {
- DEBUG(dbgs() << " compute BB '" << BB->getName()
- << "' - overdefined because inst def found.\n");
- Res.markOverdefined();
+ // If this value is a nonnull pointer, record it's range and bailout. Note
+ // that for all other pointer typed values, we terminate the search at the
+ // definition. We could easily extend this to look through geps, bitcasts,
+ // and the like to prove non-nullness, but it's not clear that's worth it
+ // compile time wise. The context-insensative value walk done inside
+ // isKnownNonNull gets most of the profitable cases at much less expense.
+ // This does mean that we have a sensativity to where the defining
+ // instruction is placed, even if it could legally be hoisted much higher.
+ // That is unfortunate.
+ PointerType *PT = dyn_cast<PointerType>(BBI->getType());
+ if (PT && isKnownNonNull(BBI)) {
+ Res = LVILatticeVal::getNot(ConstantPointerNull::get(PT));
insertResult(Val, BB, Res);
return true;
}
-
- // FIXME: We're currently limited to binops with a constant RHS. This should
- // be improved.
- BinaryOperator *BO = dyn_cast<BinaryOperator>(BBI);
- if (BO && !isa<ConstantInt>(BO->getOperand(1))) {
- DEBUG(dbgs() << " compute BB '" << BB->getName()
- << "' - overdefined because inst def found.\n");
-
- Res.markOverdefined();
- insertResult(Val, BB, Res);
- return true;
+ if (BBI->getType()->isIntegerTy()) {
+ if (isa<CastInst>(BBI)) {
+ if (!solveBlockValueCast(Res, BBI, BB))
+ return false;
+ insertResult(Val, BB, Res);
+ return true;
+ }
+ BinaryOperator *BO = dyn_cast<BinaryOperator>(BBI);
+ if (BO && isa<ConstantInt>(BO->getOperand(1))) {
+ if (!solveBlockValueBinaryOp(Res, BBI, BB))
+ return false;
+ insertResult(Val, BB, Res);
+ return true;
+ }
}
- if (!solveBlockValueConstantRange(Res, BBI, BB))
- return false;
+ DEBUG(dbgs() << " compute BB '" << BB->getName()
+ << "' - unknown inst def found.\n");
+ Res = getFromRangeMetadata(BBI);
insertResult(Val, BB, Res);
return true;
}
@@ -660,37 +730,36 @@ static bool InstructionDereferencesPointer(Instruction *I, Value *Ptr) {
return false;
}
+/// Return true if the allocation associated with Val is ever dereferenced
+/// within the given basic block. This establishes the fact Val is not null,
+/// but does not imply that the memory at Val is dereferenceable. (Val may
+/// point off the end of the dereferenceable part of the object.)
+static bool isObjectDereferencedInBlock(Value *Val, BasicBlock *BB) {
+ assert(Val->getType()->isPointerTy());
+
+ const DataLayout &DL = BB->getModule()->getDataLayout();
+ Value *UnderlyingVal = GetUnderlyingObject(Val, DL);
+ // If 'GetUnderlyingObject' didn't converge, skip it. It won't converge
+ // inside InstructionDereferencesPointer either.
+ if (UnderlyingVal == GetUnderlyingObject(UnderlyingVal, DL, 1))
+ for (Instruction &I : *BB)
+ if (InstructionDereferencesPointer(&I, UnderlyingVal))
+ return true;
+ return false;
+}
+
bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV,
Value *Val, BasicBlock *BB) {
LVILatticeVal Result; // Start Undefined.
- // If this is a pointer, and there's a load from that pointer in this BB,
- // then we know that the pointer can't be NULL.
- bool NotNull = false;
- if (Val->getType()->isPointerTy()) {
- if (isKnownNonNull(Val)) {
- NotNull = true;
- } else {
- const DataLayout &DL = BB->getModule()->getDataLayout();
- Value *UnderlyingVal = GetUnderlyingObject(Val, DL);
- // If 'GetUnderlyingObject' didn't converge, skip it. It won't converge
- // inside InstructionDereferencesPointer either.
- if (UnderlyingVal == GetUnderlyingObject(UnderlyingVal, DL, 1)) {
- for (Instruction &I : *BB) {
- if (InstructionDereferencesPointer(&I, UnderlyingVal)) {
- NotNull = true;
- break;
- }
- }
- }
- }
- }
-
// If this is the entry block, we must be asking about an argument. The
// value is overdefined.
if (BB == &BB->getParent()->getEntryBlock()) {
assert(isa<Argument>(Val) && "Unknown live-in to the entry block");
- if (NotNull) {
+ // Bofore giving up, see if we can prove the pointer non-null local to
+ // this particular block.
+ if (Val->getType()->isPointerTy() &&
+ (isKnownNonNull(Val) || isObjectDereferencedInBlock(Val, BB))) {
PointerType *PTy = cast<PointerType>(Val->getType());
Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy));
} else {
@@ -715,10 +784,11 @@ bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV,
// to overdefined.
if (Result.isOverdefined()) {
DEBUG(dbgs() << " compute BB '" << BB->getName()
- << "' - overdefined because of pred.\n");
- // If we previously determined that this is a pointer that can't be null
- // then return that rather than giving up entirely.
- if (NotNull) {
+ << "' - overdefined because of pred (non local).\n");
+ // Bofore giving up, see if we can prove the pointer non-null local to
+ // this particular block.
+ if (Val->getType()->isPointerTy() &&
+ isObjectDereferencedInBlock(Val, BB)) {
PointerType *PTy = cast<PointerType>(Val->getType());
Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy));
}
@@ -760,7 +830,7 @@ bool LazyValueInfoCache::solveBlockValuePHINode(LVILatticeVal &BBLV,
// to overdefined.
if (Result.isOverdefined()) {
DEBUG(dbgs() << " compute BB '" << BB->getName()
- << "' - overdefined because of pred.\n");
+ << "' - overdefined because of pred (local).\n");
BBLV = Result;
return true;
@@ -779,10 +849,9 @@ static bool getValueFromFromCondition(Value *Val, ICmpInst *ICI,
LVILatticeVal &Result,
bool isTrueDest = true);
-// If we can determine a constant range for the value Val in the context
-// provided by the instruction BBI, then merge it into BBLV. If we did find a
-// constant range, return true.
-void LazyValueInfoCache::mergeAssumeBlockValueConstantRange(Value *Val,
+// If we can determine a constraint on the value given conditions assumed by
+// the program, intersect those constraints with BBLV
+void LazyValueInfoCache::intersectAssumeBlockValueConstantRange(Value *Val,
LVILatticeVal &BBLV,
Instruction *BBI) {
BBI = BBI ? BBI : dyn_cast<Instruction>(Val);
@@ -799,46 +868,264 @@ void LazyValueInfoCache::mergeAssumeBlockValueConstantRange(Value *Val,
Value *C = I->getArgOperand(0);
if (ICmpInst *ICI = dyn_cast<ICmpInst>(C)) {
LVILatticeVal Result;
- if (getValueFromFromCondition(Val, ICI, Result)) {
- if (BBLV.isOverdefined())
- BBLV = Result;
- else
- BBLV.mergeIn(Result, DL);
- }
+ if (getValueFromFromCondition(Val, ICI, Result))
+ BBLV = intersect(BBLV, Result);
}
}
}
-bool LazyValueInfoCache::solveBlockValueConstantRange(LVILatticeVal &BBLV,
- Instruction *BBI,
- BasicBlock *BB) {
- // Figure out the range of the LHS. If that fails, bail.
- if (!hasBlockValue(BBI->getOperand(0), BB)) {
- if (pushBlockValue(std::make_pair(BB, BBI->getOperand(0))))
+bool LazyValueInfoCache::solveBlockValueSelect(LVILatticeVal &BBLV,
+ SelectInst *SI, BasicBlock *BB) {
+
+ // Recurse on our inputs if needed
+ if (!hasBlockValue(SI->getTrueValue(), BB)) {
+ if (pushBlockValue(std::make_pair(BB, SI->getTrueValue())))
return false;
BBLV.markOverdefined();
return true;
}
+ LVILatticeVal TrueVal = getBlockValue(SI->getTrueValue(), BB);
+ // If we hit overdefined, don't ask more queries. We want to avoid poisoning
+ // extra slots in the table if we can.
+ if (TrueVal.isOverdefined()) {
+ BBLV.markOverdefined();
+ return true;
+ }
- LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB);
- mergeAssumeBlockValueConstantRange(BBI->getOperand(0), LHSVal, BBI);
- if (!LHSVal.isConstantRange()) {
+ if (!hasBlockValue(SI->getFalseValue(), BB)) {
+ if (pushBlockValue(std::make_pair(BB, SI->getFalseValue())))
+ return false;
+ BBLV.markOverdefined();
+ return true;
+ }
+ LVILatticeVal FalseVal = getBlockValue(SI->getFalseValue(), BB);
+ // If we hit overdefined, don't ask more queries. We want to avoid poisoning
+ // extra slots in the table if we can.
+ if (FalseVal.isOverdefined()) {
BBLV.markOverdefined();
return true;
}
- ConstantRange LHSRange = LHSVal.getConstantRange();
- ConstantRange RHSRange(1);
- IntegerType *ResultTy = cast<IntegerType>(BBI->getType());
- if (isa<BinaryOperator>(BBI)) {
- if (ConstantInt *RHS = dyn_cast<ConstantInt>(BBI->getOperand(1))) {
- RHSRange = ConstantRange(RHS->getValue());
- } else {
- BBLV.markOverdefined();
- return true;
+ if (TrueVal.isConstantRange() && FalseVal.isConstantRange()) {
+ ConstantRange TrueCR = TrueVal.getConstantRange();
+ ConstantRange FalseCR = FalseVal.getConstantRange();
+ Value *LHS = nullptr;
+ Value *RHS = nullptr;
+ SelectPatternResult SPR = matchSelectPattern(SI, LHS, RHS);
+ // Is this a min specifically of our two inputs? (Avoid the risk of
+ // ValueTracking getting smarter looking back past our immediate inputs.)
+ if (SelectPatternResult::isMinOrMax(SPR.Flavor) &&
+ LHS == SI->getTrueValue() && RHS == SI->getFalseValue()) {
+ switch (SPR.Flavor) {
+ default:
+ llvm_unreachable("unexpected minmax type!");
+ case SPF_SMIN: /// Signed minimum
+ BBLV.markConstantRange(TrueCR.smin(FalseCR));
+ return true;
+ case SPF_UMIN: /// Unsigned minimum
+ BBLV.markConstantRange(TrueCR.umin(FalseCR));
+ return true;
+ case SPF_SMAX: /// Signed maximum
+ BBLV.markConstantRange(TrueCR.smax(FalseCR));
+ return true;
+ case SPF_UMAX: /// Unsigned maximum
+ BBLV.markConstantRange(TrueCR.umax(FalseCR));
+ return true;
+ };
+ }
+
+ // TODO: ABS, NABS from the SelectPatternResult
+ }
+
+ // Can we constrain the facts about the true and false values by using the
+ // condition itself? This shows up with idioms like e.g. select(a > 5, a, 5).
+ // TODO: We could potentially refine an overdefined true value above.
+ if (auto *ICI = dyn_cast<ICmpInst>(SI->getCondition())) {
+ LVILatticeVal TrueValTaken, FalseValTaken;
+ if (!getValueFromFromCondition(SI->getTrueValue(), ICI,
+ TrueValTaken, true))
+ TrueValTaken.markOverdefined();
+ if (!getValueFromFromCondition(SI->getFalseValue(), ICI,
+ FalseValTaken, false))
+ FalseValTaken.markOverdefined();
+
+ TrueVal = intersect(TrueVal, TrueValTaken);
+ FalseVal = intersect(FalseVal, FalseValTaken);
+
+
+ // Handle clamp idioms such as:
+ // %24 = constantrange<0, 17>
+ // %39 = icmp eq i32 %24, 0
+ // %40 = add i32 %24, -1
+ // %siv.next = select i1 %39, i32 16, i32 %40
+ // %siv.next = constantrange<0, 17> not <-1, 17>
+ // In general, this can handle any clamp idiom which tests the edge
+ // condition via an equality or inequality.
+ ICmpInst::Predicate Pred = ICI->getPredicate();
+ Value *A = ICI->getOperand(0);
+ if (ConstantInt *CIBase = dyn_cast<ConstantInt>(ICI->getOperand(1))) {
+ auto addConstants = [](ConstantInt *A, ConstantInt *B) {
+ assert(A->getType() == B->getType());
+ return ConstantInt::get(A->getType(), A->getValue() + B->getValue());
+ };
+ // See if either input is A + C2, subject to the constraint from the
+ // condition that A != C when that input is used. We can assume that
+ // that input doesn't include C + C2.
+ ConstantInt *CIAdded;
+ switch (Pred) {
+ default: break;
+ case ICmpInst::ICMP_EQ:
+ if (match(SI->getFalseValue(), m_Add(m_Specific(A),
+ m_ConstantInt(CIAdded)))) {
+ auto ResNot = addConstants(CIBase, CIAdded);
+ FalseVal = intersect(FalseVal,
+ LVILatticeVal::getNot(ResNot));
+ }
+ break;
+ case ICmpInst::ICMP_NE:
+ if (match(SI->getTrueValue(), m_Add(m_Specific(A),
+ m_ConstantInt(CIAdded)))) {
+ auto ResNot = addConstants(CIBase, CIAdded);
+ TrueVal = intersect(TrueVal,
+ LVILatticeVal::getNot(ResNot));
+ }
+ break;
+ };
}
}
+ LVILatticeVal Result; // Start Undefined.
+ Result.mergeIn(TrueVal, DL);
+ Result.mergeIn(FalseVal, DL);
+ BBLV = Result;
+ return true;
+}
+
+bool LazyValueInfoCache::solveBlockValueCast(LVILatticeVal &BBLV,
+ Instruction *BBI,
+ BasicBlock *BB) {
+ if (!BBI->getOperand(0)->getType()->isSized()) {
+ // Without knowing how wide the input is, we can't analyze it in any useful
+ // way.
+ BBLV.markOverdefined();
+ return true;
+ }
+
+ // Filter out casts we don't know how to reason about before attempting to
+ // recurse on our operand. This can cut a long search short if we know we're
+ // not going to be able to get any useful information anways.
+ switch (BBI->getOpcode()) {
+ case Instruction::Trunc:
+ case Instruction::SExt:
+ case Instruction::ZExt:
+ case Instruction::BitCast:
+ break;
+ default:
+ // Unhandled instructions are overdefined.
+ DEBUG(dbgs() << " compute BB '" << BB->getName()
+ << "' - overdefined (unknown cast).\n");
+ BBLV.markOverdefined();
+ return true;
+ }
+
+ // Figure out the range of the LHS. If that fails, we still apply the
+ // transfer rule on the full set since we may be able to locally infer
+ // interesting facts.
+ if (!hasBlockValue(BBI->getOperand(0), BB))
+ if (pushBlockValue(std::make_pair(BB, BBI->getOperand(0))))
+ // More work to do before applying this transfer rule.
+ return false;
+
+ const unsigned OperandBitWidth =
+ DL.getTypeSizeInBits(BBI->getOperand(0)->getType());
+ ConstantRange LHSRange = ConstantRange(OperandBitWidth);
+ if (hasBlockValue(BBI->getOperand(0), BB)) {
+ LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB);
+ intersectAssumeBlockValueConstantRange(BBI->getOperand(0), LHSVal, BBI);
+ if (LHSVal.isConstantRange())
+ LHSRange = LHSVal.getConstantRange();
+ }
+
+ const unsigned ResultBitWidth =
+ cast<IntegerType>(BBI->getType())->getBitWidth();
+
+ // NOTE: We're currently limited by the set of operations that ConstantRange
+ // can evaluate symbolically. Enhancing that set will allows us to analyze
+ // more definitions.
+ LVILatticeVal Result;
+ switch (BBI->getOpcode()) {
+ case Instruction::Trunc:
+ Result.markConstantRange(LHSRange.truncate(ResultBitWidth));
+ break;
+ case Instruction::SExt:
+ Result.markConstantRange(LHSRange.signExtend(ResultBitWidth));
+ break;
+ case Instruction::ZExt:
+ Result.markConstantRange(LHSRange.zeroExtend(ResultBitWidth));
+ break;
+ case Instruction::BitCast:
+ Result.markConstantRange(LHSRange);
+ break;
+ default:
+ // Should be dead if the code above is correct
+ llvm_unreachable("inconsistent with above");
+ break;
+ }
+
+ BBLV = Result;
+ return true;
+}
+
+bool LazyValueInfoCache::solveBlockValueBinaryOp(LVILatticeVal &BBLV,
+ Instruction *BBI,
+ BasicBlock *BB) {
+
+ assert(BBI->getOperand(0)->getType()->isSized() &&
+ "all operands to binary operators are sized");
+
+ // Filter out operators we don't know how to reason about before attempting to
+ // recurse on our operand(s). This can cut a long search short if we know
+ // we're not going to be able to get any useful information anways.
+ switch (BBI->getOpcode()) {
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Mul:
+ case Instruction::UDiv:
+ case Instruction::Shl:
+ case Instruction::LShr:
+ case Instruction::And:
+ case Instruction::Or:
+ // continue into the code below
+ break;
+ default:
+ // Unhandled instructions are overdefined.
+ DEBUG(dbgs() << " compute BB '" << BB->getName()
+ << "' - overdefined (unknown binary operator).\n");
+ BBLV.markOverdefined();
+ return true;
+ };
+
+ // Figure out the range of the LHS. If that fails, use a conservative range,
+ // but apply the transfer rule anyways. This lets us pick up facts from
+ // expressions like "and i32 (call i32 @foo()), 32"
+ if (!hasBlockValue(BBI->getOperand(0), BB))
+ if (pushBlockValue(std::make_pair(BB, BBI->getOperand(0))))
+ // More work to do before applying this transfer rule.
+ return false;
+
+ const unsigned OperandBitWidth =
+ DL.getTypeSizeInBits(BBI->getOperand(0)->getType());
+ ConstantRange LHSRange = ConstantRange(OperandBitWidth);
+ if (hasBlockValue(BBI->getOperand(0), BB)) {
+ LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB);
+ intersectAssumeBlockValueConstantRange(BBI->getOperand(0), LHSVal, BBI);
+ if (LHSVal.isConstantRange())
+ LHSRange = LHSVal.getConstantRange();
+ }
+
+ ConstantInt *RHS = cast<ConstantInt>(BBI->getOperand(1));
+ ConstantRange RHSRange = ConstantRange(RHS->getValue());
+
// NOTE: We're currently limited by the set of operations that ConstantRange
// can evaluate symbolically. Enhancing that set will allows us to analyze
// more definitions.
@@ -862,30 +1149,15 @@ bool LazyValueInfoCache::solveBlockValueConstantRange(LVILatticeVal &BBLV,
case Instruction::LShr:
Result.markConstantRange(LHSRange.lshr(RHSRange));
break;
- case Instruction::Trunc:
- Result.markConstantRange(LHSRange.truncate(ResultTy->getBitWidth()));
- break;
- case Instruction::SExt:
- Result.markConstantRange(LHSRange.signExtend(ResultTy->getBitWidth()));
- break;
- case Instruction::ZExt:
- Result.markConstantRange(LHSRange.zeroExtend(ResultTy->getBitWidth()));
- break;
- case Instruction::BitCast:
- Result.markConstantRange(LHSRange);
- break;
case Instruction::And:
Result.markConstantRange(LHSRange.binaryAnd(RHSRange));
break;
case Instruction::Or:
Result.markConstantRange(LHSRange.binaryOr(RHSRange));
break;
-
- // Unhandled instructions are overdefined.
default:
- DEBUG(dbgs() << " compute BB '" << BB->getName()
- << "' - overdefined because inst def found.\n");
- Result.markOverdefined();
+ // Should be dead if the code above is correct
+ llvm_unreachable("inconsistent with above");
break;
}
@@ -895,10 +1167,11 @@ bool LazyValueInfoCache::solveBlockValueConstantRange(LVILatticeVal &BBLV,
bool getValueFromFromCondition(Value *Val, ICmpInst *ICI,
LVILatticeVal &Result, bool isTrueDest) {
- if (ICI && isa<Constant>(ICI->getOperand(1))) {
+ assert(ICI && "precondition");
+ if (isa<Constant>(ICI->getOperand(1))) {
if (ICI->isEquality() && ICI->getOperand(0) == Val) {
// We know that V has the RHS constant if this is a true SETEQ or
- // false SETNE.
+ // false SETNE.
if (isTrueDest == (ICI->getPredicate() == ICmpInst::ICMP_EQ))
Result = LVILatticeVal::get(cast<Constant>(ICI->getOperand(1)));
else
@@ -926,7 +1199,7 @@ bool getValueFromFromCondition(Value *Val, ICmpInst *ICI,
// If we're interested in the false dest, invert the condition.
if (!isTrueDest) TrueValues = TrueValues.inverse();
- Result = LVILatticeVal::getRange(TrueValues);
+ Result = LVILatticeVal::getRange(std::move(TrueValues));
return true;
}
}
@@ -935,7 +1208,8 @@ bool getValueFromFromCondition(Value *Val, ICmpInst *ICI,
}
/// \brief Compute the value of Val on the edge BBFrom -> BBTo. Returns false if
-/// Val is not constrained on the edge.
+/// Val is not constrained on the edge. Result is unspecified if return value
+/// is false.
static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
BasicBlock *BBTo, LVILatticeVal &Result) {
// TODO: Handle more complex conditionals. If (v == 0 || v2 < 1) is false, we
@@ -985,7 +1259,7 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
} else if (i.getCaseSuccessor() == BBTo)
EdgesVals = EdgesVals.unionWith(EdgeVal);
}
- Result = LVILatticeVal::getRange(EdgesVals);
+ Result = LVILatticeVal::getRange(std::move(EdgesVals));
return true;
}
return false;
@@ -1002,46 +1276,29 @@ bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom,
return true;
}
- if (getEdgeValueLocal(Val, BBFrom, BBTo, Result)) {
- if (!Result.isConstantRange() ||
- Result.getConstantRange().getSingleElement())
- return true;
-
- // FIXME: this check should be moved to the beginning of the function when
- // LVI better supports recursive values. Even for the single value case, we
- // can intersect to detect dead code (an empty range).
- if (!hasBlockValue(Val, BBFrom)) {
- if (pushBlockValue(std::make_pair(BBFrom, Val)))
- return false;
- Result.markOverdefined();
- return true;
- }
-
- // Try to intersect ranges of the BB and the constraint on the edge.
- LVILatticeVal InBlock = getBlockValue(Val, BBFrom);
- mergeAssumeBlockValueConstantRange(Val, InBlock, BBFrom->getTerminator());
- // See note on the use of the CxtI with mergeAssumeBlockValueConstantRange,
- // and caching, below.
- mergeAssumeBlockValueConstantRange(Val, InBlock, CxtI);
- if (!InBlock.isConstantRange())
- return true;
+ LVILatticeVal LocalResult;
+ if (!getEdgeValueLocal(Val, BBFrom, BBTo, LocalResult))
+ // If we couldn't constrain the value on the edge, LocalResult doesn't
+ // provide any information.
+ LocalResult.markOverdefined();
- ConstantRange Range =
- Result.getConstantRange().intersectWith(InBlock.getConstantRange());
- Result = LVILatticeVal::getRange(Range);
+ if (hasSingleValue(LocalResult)) {
+ // Can't get any more precise here
+ Result = LocalResult;
return true;
}
if (!hasBlockValue(Val, BBFrom)) {
if (pushBlockValue(std::make_pair(BBFrom, Val)))
return false;
- Result.markOverdefined();
+ // No new information.
+ Result = LocalResult;
return true;
}
- // If we couldn't compute the value on the edge, use the value from the BB.
- Result = getBlockValue(Val, BBFrom);
- mergeAssumeBlockValueConstantRange(Val, Result, BBFrom->getTerminator());
+ // Try to intersect ranges of the BB and the constraint on the edge.
+ LVILatticeVal InBlock = getBlockValue(Val, BBFrom);
+ intersectAssumeBlockValueConstantRange(Val, InBlock, BBFrom->getTerminator());
// We can use the context instruction (generically the ultimate instruction
// the calling pass is trying to simplify) here, even though the result of
// this function is generally cached when called from the solve* functions
@@ -1050,7 +1307,9 @@ bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom,
// functions, the context instruction is not provided. When called from
// LazyValueInfoCache::getValueOnEdge, the context instruction is provided,
// but then the result is not cached.
- mergeAssumeBlockValueConstantRange(Val, Result, CxtI);
+ intersectAssumeBlockValueConstantRange(Val, InBlock, CxtI);
+
+ Result = intersect(LocalResult, InBlock);
return true;
}
@@ -1060,11 +1319,12 @@ LVILatticeVal LazyValueInfoCache::getValueInBlock(Value *V, BasicBlock *BB,
<< BB->getName() << "'\n");
assert(BlockValueStack.empty() && BlockValueSet.empty());
- pushBlockValue(std::make_pair(BB, V));
-
- solve();
+ if (!hasBlockValue(V, BB)) {
+ pushBlockValue(std::make_pair(BB, V));
+ solve();
+ }
LVILatticeVal Result = getBlockValue(V, BB);
- mergeAssumeBlockValueConstantRange(V, Result, CxtI);
+ intersectAssumeBlockValueConstantRange(V, Result, CxtI);
DEBUG(dbgs() << " Result = " << Result << "\n");
return Result;
@@ -1074,10 +1334,13 @@ LVILatticeVal LazyValueInfoCache::getValueAt(Value *V, Instruction *CxtI) {
DEBUG(dbgs() << "LVI Getting value " << *V << " at '"
<< CxtI->getName() << "'\n");
- LVILatticeVal Result;
+ if (auto *C = dyn_cast<Constant>(V))
+ return LVILatticeVal::get(C);
+
+ LVILatticeVal Result = LVILatticeVal::getOverdefined();
if (auto *I = dyn_cast<Instruction>(V))
Result = getFromRangeMetadata(I);
- mergeAssumeBlockValueConstantRange(V, Result, CxtI);
+ intersectAssumeBlockValueConstantRange(V, Result, CxtI);
DEBUG(dbgs() << " Result = " << Result << "\n");
return Result;
@@ -1172,29 +1435,32 @@ static LazyValueInfoCache &getCache(void *&PImpl, AssumptionCache *AC,
return *static_cast<LazyValueInfoCache*>(PImpl);
}
-bool LazyValueInfo::runOnFunction(Function &F) {
- AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
+bool LazyValueInfoWrapperPass::runOnFunction(Function &F) {
+ Info.AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
const DataLayout &DL = F.getParent()->getDataLayout();
DominatorTreeWrapperPass *DTWP =
getAnalysisIfAvailable<DominatorTreeWrapperPass>();
- DT = DTWP ? &DTWP->getDomTree() : nullptr;
-
- TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
+ Info.DT = DTWP ? &DTWP->getDomTree() : nullptr;
+ Info.TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
- if (PImpl)
- getCache(PImpl, AC, &DL, DT).clear();
+ if (Info.PImpl)
+ getCache(Info.PImpl, Info.AC, &DL, Info.DT).clear();
// Fully lazy.
return false;
}
-void LazyValueInfo::getAnalysisUsage(AnalysisUsage &AU) const {
+void LazyValueInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<AssumptionCacheTracker>();
AU.addRequired<TargetLibraryInfoWrapperPass>();
}
+LazyValueInfo &LazyValueInfoWrapperPass::getLVI() { return Info; }
+
+LazyValueInfo::~LazyValueInfo() { releaseMemory(); }
+
void LazyValueInfo::releaseMemory() {
// If the cache was allocated, free it.
if (PImpl) {
@@ -1203,6 +1469,16 @@ void LazyValueInfo::releaseMemory() {
}
}
+void LazyValueInfoWrapperPass::releaseMemory() { Info.releaseMemory(); }
+
+LazyValueInfo LazyValueAnalysis::run(Function &F, FunctionAnalysisManager &FAM) {
+ auto &AC = FAM.getResult<AssumptionAnalysis>(F);
+ auto &TLI = FAM.getResult<TargetLibraryAnalysis>(F);
+ auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(F);
+
+ return LazyValueInfo(&AC, &TLI, DT);
+}
+
/// Returns true if we can statically tell that this value will never be a
/// "useful" constant. In practice, this means we've got something like an
@@ -1238,6 +1514,21 @@ Constant *LazyValueInfo::getConstant(Value *V, BasicBlock *BB,
return nullptr;
}
+ConstantRange LazyValueInfo::getConstantRange(Value *V, BasicBlock *BB,
+ Instruction *CxtI) {
+ assert(V->getType()->isIntegerTy());
+ unsigned Width = V->getType()->getIntegerBitWidth();
+ const DataLayout &DL = BB->getModule()->getDataLayout();
+ LVILatticeVal Result =
+ getCache(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI);
+ assert(!Result.isConstant());
+ if (Result.isUndefined())
+ return ConstantRange(Width, /*isFullSet=*/false);
+ if (Result.isConstantRange())
+ return Result.getConstantRange();
+ return ConstantRange(Width, /*isFullSet=*/true);
+}
+
/// Determine whether the specified value is known to be a
/// constant on the specified edge. Return null if not.
Constant *LazyValueInfo::getConstantOnEdge(Value *V, BasicBlock *FromBB,
@@ -1379,7 +1670,7 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C,
// We limit the search to one step backwards from the current BB and value.
// We could consider extending this to search further backwards through the
// CFG and/or value graph, but there are non-obvious compile time vs quality
- // tradeoffs.
+ // tradeoffs.
if (CxtI) {
BasicBlock *BB = CxtI->getParent();
@@ -1399,10 +1690,10 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C,
for (unsigned i = 0, e = PHI->getNumIncomingValues(); i < e; i++) {
Value *Incoming = PHI->getIncomingValue(i);
BasicBlock *PredBB = PHI->getIncomingBlock(i);
- // Note that PredBB may be BB itself.
+ // Note that PredBB may be BB itself.
Tristate Result = getPredicateOnEdge(Pred, Incoming, C, PredBB, BB,
CxtI);
-
+
// Keep going as long as we've seen a consistent known result for
// all inputs.
Baseline = (i == 0) ? Result /* First iteration */
OpenPOWER on IntegriCloud