aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/LazyValueInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/LazyValueInfo.cpp')
-rw-r--r--llvm/lib/Analysis/LazyValueInfo.cpp315
1 files changed, 200 insertions, 115 deletions
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index 2fae260e0d8f..f1587cecf9fb 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -13,7 +13,6 @@
#include "llvm/Analysis/LazyValueInfo.h"
#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/ConstantFolding.h"
@@ -38,6 +37,7 @@
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/raw_ostream.h"
+#include <optional>
using namespace llvm;
using namespace PatternMatch;
@@ -164,7 +164,7 @@ namespace {
SmallDenseSet<AssertingVH<Value>, 4> OverDefined;
// None indicates that the nonnull pointers for this basic block
// block have not been computed yet.
- Optional<NonNullPointerSet> NonNullPointers;
+ std::optional<NonNullPointerSet> NonNullPointers;
};
/// Cached information per basic block.
@@ -210,18 +210,18 @@ namespace {
addValueHandle(Val);
}
- Optional<ValueLatticeElement> getCachedValueInfo(Value *V,
- BasicBlock *BB) const {
+ std::optional<ValueLatticeElement>
+ getCachedValueInfo(Value *V, BasicBlock *BB) const {
const BlockCacheEntry *Entry = getBlockEntry(BB);
if (!Entry)
- return None;
+ return std::nullopt;
if (Entry->OverDefined.count(V))
return ValueLatticeElement::getOverdefined();
auto LatticeIt = Entry->LatticeElements.find_as(V);
if (LatticeIt == Entry->LatticeElements.end())
- return None;
+ return std::nullopt;
return LatticeIt->second;
}
@@ -394,38 +394,40 @@ class LazyValueInfoImpl {
/// if it exists in the module.
Function *GuardDecl;
- Optional<ValueLatticeElement> getBlockValue(Value *Val, BasicBlock *BB,
- Instruction *CxtI);
- Optional<ValueLatticeElement> getEdgeValue(Value *V, BasicBlock *F,
- BasicBlock *T, Instruction *CxtI = nullptr);
+ std::optional<ValueLatticeElement> getBlockValue(Value *Val, BasicBlock *BB,
+ Instruction *CxtI);
+ std::optional<ValueLatticeElement> getEdgeValue(Value *V, BasicBlock *F,
+ BasicBlock *T,
+ Instruction *CxtI = nullptr);
// 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);
- Optional<ValueLatticeElement> solveBlockValueImpl(Value *Val, BasicBlock *BB);
- Optional<ValueLatticeElement> solveBlockValueNonLocal(Value *Val,
- BasicBlock *BB);
- Optional<ValueLatticeElement> solveBlockValuePHINode(PHINode *PN,
- BasicBlock *BB);
- Optional<ValueLatticeElement> solveBlockValueSelect(SelectInst *S,
- BasicBlock *BB);
- Optional<ConstantRange> getRangeFor(Value *V, Instruction *CxtI,
- BasicBlock *BB);
- Optional<ValueLatticeElement> solveBlockValueBinaryOpImpl(
+ std::optional<ValueLatticeElement> solveBlockValueImpl(Value *Val,
+ BasicBlock *BB);
+ std::optional<ValueLatticeElement> solveBlockValueNonLocal(Value *Val,
+ BasicBlock *BB);
+ std::optional<ValueLatticeElement> solveBlockValuePHINode(PHINode *PN,
+ BasicBlock *BB);
+ std::optional<ValueLatticeElement> solveBlockValueSelect(SelectInst *S,
+ BasicBlock *BB);
+ std::optional<ConstantRange> getRangeFor(Value *V, Instruction *CxtI,
+ BasicBlock *BB);
+ std::optional<ValueLatticeElement> solveBlockValueBinaryOpImpl(
Instruction *I, BasicBlock *BB,
- std::function<ConstantRange(const ConstantRange &,
- const ConstantRange &)> OpFn);
- Optional<ValueLatticeElement> solveBlockValueBinaryOp(BinaryOperator *BBI,
- BasicBlock *BB);
- Optional<ValueLatticeElement> solveBlockValueCast(CastInst *CI,
- BasicBlock *BB);
- Optional<ValueLatticeElement> solveBlockValueOverflowIntrinsic(
- WithOverflowInst *WO, BasicBlock *BB);
- Optional<ValueLatticeElement> solveBlockValueIntrinsic(IntrinsicInst *II,
+ std::function<ConstantRange(const ConstantRange &, const ConstantRange &)>
+ OpFn);
+ std::optional<ValueLatticeElement>
+ solveBlockValueBinaryOp(BinaryOperator *BBI, BasicBlock *BB);
+ std::optional<ValueLatticeElement> solveBlockValueCast(CastInst *CI,
BasicBlock *BB);
- Optional<ValueLatticeElement> solveBlockValueExtractValue(
- ExtractValueInst *EVI, BasicBlock *BB);
+ std::optional<ValueLatticeElement>
+ solveBlockValueOverflowIntrinsic(WithOverflowInst *WO, BasicBlock *BB);
+ std::optional<ValueLatticeElement> solveBlockValueIntrinsic(IntrinsicInst *II,
+ BasicBlock *BB);
+ std::optional<ValueLatticeElement>
+ solveBlockValueExtractValue(ExtractValueInst *EVI, BasicBlock *BB);
bool isNonNullAtEndOfBlock(Value *Val, BasicBlock *BB);
void intersectAssumeOrGuardBlockValueConstantRange(Value *Val,
ValueLatticeElement &BBLV,
@@ -516,7 +518,7 @@ void LazyValueInfoImpl::solve() {
// The work item was completely processed.
assert(BlockValueStack.back() == e && "Nothing should have been pushed!");
#ifndef NDEBUG
- Optional<ValueLatticeElement> BBLV =
+ std::optional<ValueLatticeElement> BBLV =
TheCache.getCachedValueInfo(e.second, e.first);
assert(BBLV && "Result should be in cache!");
LLVM_DEBUG(
@@ -533,13 +535,14 @@ void LazyValueInfoImpl::solve() {
}
}
-Optional<ValueLatticeElement> LazyValueInfoImpl::getBlockValue(
- Value *Val, BasicBlock *BB, Instruction *CxtI) {
+std::optional<ValueLatticeElement>
+LazyValueInfoImpl::getBlockValue(Value *Val, BasicBlock *BB,
+ Instruction *CxtI) {
// If already a constant, there is nothing to compute.
if (Constant *VC = dyn_cast<Constant>(Val))
return ValueLatticeElement::get(VC);
- if (Optional<ValueLatticeElement> OptLatticeVal =
+ if (std::optional<ValueLatticeElement> OptLatticeVal =
TheCache.getCachedValueInfo(Val, BB)) {
intersectAssumeOrGuardBlockValueConstantRange(Val, *OptLatticeVal, CxtI);
return OptLatticeVal;
@@ -550,7 +553,7 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::getBlockValue(
return ValueLatticeElement::getOverdefined();
// Yet to be resolved.
- return None;
+ return std::nullopt;
}
static ValueLatticeElement getFromRangeMetadata(Instruction *BBI) {
@@ -577,7 +580,7 @@ bool LazyValueInfoImpl::solveBlockValue(Value *Val, BasicBlock *BB) {
// Hold off inserting this value into the Cache in case we have to return
// false and come back later.
- Optional<ValueLatticeElement> Res = solveBlockValueImpl(Val, BB);
+ std::optional<ValueLatticeElement> Res = solveBlockValueImpl(Val, BB);
if (!Res)
// Work pushed, will revisit
return false;
@@ -586,8 +589,8 @@ bool LazyValueInfoImpl::solveBlockValue(Value *Val, BasicBlock *BB) {
return true;
}
-Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueImpl(
- Value *Val, BasicBlock *BB) {
+std::optional<ValueLatticeElement>
+LazyValueInfoImpl::solveBlockValueImpl(Value *Val, BasicBlock *BB) {
Instruction *BBI = dyn_cast<Instruction>(Val);
if (!BBI || BBI->getParent() != BB)
return solveBlockValueNonLocal(Val, BB);
@@ -669,8 +672,8 @@ bool LazyValueInfoImpl::isNonNullAtEndOfBlock(Value *Val, BasicBlock *BB) {
});
}
-Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueNonLocal(
- Value *Val, BasicBlock *BB) {
+std::optional<ValueLatticeElement>
+LazyValueInfoImpl::solveBlockValueNonLocal(Value *Val, BasicBlock *BB) {
ValueLatticeElement Result; // Start Undefined.
// If this is the entry block, we must be asking about an argument. The
@@ -690,10 +693,10 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueNonLocal(
// canonicalizing to make this true rather than relying on this happy
// accident.
for (BasicBlock *Pred : predecessors(BB)) {
- Optional<ValueLatticeElement> EdgeResult = getEdgeValue(Val, Pred, BB);
+ std::optional<ValueLatticeElement> EdgeResult = getEdgeValue(Val, Pred, BB);
if (!EdgeResult)
// Explore that input, then return here
- return None;
+ return std::nullopt;
Result.mergeIn(*EdgeResult);
@@ -701,7 +704,8 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueNonLocal(
// to overdefined.
if (Result.isOverdefined()) {
LLVM_DEBUG(dbgs() << " compute BB '" << BB->getName()
- << "' - overdefined because of pred (non local).\n");
+ << "' - overdefined because of pred '"
+ << Pred->getName() << "' (non local).\n");
return Result;
}
}
@@ -711,8 +715,8 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueNonLocal(
return Result;
}
-Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValuePHINode(
- PHINode *PN, BasicBlock *BB) {
+std::optional<ValueLatticeElement>
+LazyValueInfoImpl::solveBlockValuePHINode(PHINode *PN, BasicBlock *BB) {
ValueLatticeElement Result; // Start Undefined.
// Loop over all of our predecessors, merging what we know from them into
@@ -724,11 +728,11 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValuePHINode(
// Note that we can provide PN as the context value to getEdgeValue, even
// though the results will be cached, because PN is the value being used as
// the cache key in the caller.
- Optional<ValueLatticeElement> EdgeResult =
+ std::optional<ValueLatticeElement> EdgeResult =
getEdgeValue(PhiVal, PhiBB, BB, PN);
if (!EdgeResult)
// Explore that input, then return here
- return None;
+ return std::nullopt;
Result.mergeIn(*EdgeResult);
@@ -801,19 +805,19 @@ static ConstantRange getConstantRangeOrFull(const ValueLatticeElement &Val,
return ConstantRange::getFull(DL.getTypeSizeInBits(Ty));
}
-Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueSelect(
- SelectInst *SI, BasicBlock *BB) {
+std::optional<ValueLatticeElement>
+LazyValueInfoImpl::solveBlockValueSelect(SelectInst *SI, BasicBlock *BB) {
// Recurse on our inputs if needed
- Optional<ValueLatticeElement> OptTrueVal =
+ std::optional<ValueLatticeElement> OptTrueVal =
getBlockValue(SI->getTrueValue(), BB, SI);
if (!OptTrueVal)
- return None;
+ return std::nullopt;
ValueLatticeElement &TrueVal = *OptTrueVal;
- Optional<ValueLatticeElement> OptFalseVal =
+ std::optional<ValueLatticeElement> OptFalseVal =
getBlockValue(SI->getFalseValue(), BB, SI);
if (!OptFalseVal)
- return None;
+ return std::nullopt;
ValueLatticeElement &FalseVal = *OptFalseVal;
if (TrueVal.isConstantRange() || FalseVal.isConstantRange()) {
@@ -882,17 +886,16 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueSelect(
return Result;
}
-Optional<ConstantRange> LazyValueInfoImpl::getRangeFor(Value *V,
- Instruction *CxtI,
- BasicBlock *BB) {
- Optional<ValueLatticeElement> OptVal = getBlockValue(V, BB, CxtI);
+std::optional<ConstantRange>
+LazyValueInfoImpl::getRangeFor(Value *V, Instruction *CxtI, BasicBlock *BB) {
+ std::optional<ValueLatticeElement> OptVal = getBlockValue(V, BB, CxtI);
if (!OptVal)
- return None;
+ return std::nullopt;
return getConstantRangeOrFull(*OptVal, V->getType(), DL);
}
-Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueCast(
- CastInst *CI, BasicBlock *BB) {
+std::optional<ValueLatticeElement>
+LazyValueInfoImpl::solveBlockValueCast(CastInst *CI, BasicBlock *BB) {
// Without knowing how wide the input is, we can't analyze it in any useful
// way.
if (!CI->getOperand(0)->getType()->isSized())
@@ -917,11 +920,11 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueCast(
// 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.
- Optional<ConstantRange> LHSRes = getRangeFor(CI->getOperand(0), CI, BB);
+ std::optional<ConstantRange> LHSRes = getRangeFor(CI->getOperand(0), CI, BB);
if (!LHSRes)
// More work to do before applying this transfer rule.
- return None;
- const ConstantRange &LHSRange = LHSRes.value();
+ return std::nullopt;
+ const ConstantRange &LHSRange = *LHSRes;
const unsigned ResultBitWidth = CI->getType()->getIntegerBitWidth();
@@ -932,27 +935,28 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueCast(
ResultBitWidth));
}
-Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueBinaryOpImpl(
+std::optional<ValueLatticeElement>
+LazyValueInfoImpl::solveBlockValueBinaryOpImpl(
Instruction *I, BasicBlock *BB,
- std::function<ConstantRange(const ConstantRange &,
- const ConstantRange &)> OpFn) {
+ std::function<ConstantRange(const ConstantRange &, const ConstantRange &)>
+ OpFn) {
// Figure out the ranges of the operands. 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"
- Optional<ConstantRange> LHSRes = getRangeFor(I->getOperand(0), I, BB);
- Optional<ConstantRange> RHSRes = getRangeFor(I->getOperand(1), I, BB);
+ std::optional<ConstantRange> LHSRes = getRangeFor(I->getOperand(0), I, BB);
+ std::optional<ConstantRange> RHSRes = getRangeFor(I->getOperand(1), I, BB);
if (!LHSRes || !RHSRes)
// More work to do before applying this transfer rule.
- return None;
+ return std::nullopt;
- const ConstantRange &LHSRange = LHSRes.value();
- const ConstantRange &RHSRange = RHSRes.value();
+ const ConstantRange &LHSRange = *LHSRes;
+ const ConstantRange &RHSRange = *RHSRes;
return ValueLatticeElement::getRange(OpFn(LHSRange, RHSRange));
}
-Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueBinaryOp(
- BinaryOperator *BO, BasicBlock *BB) {
+std::optional<ValueLatticeElement>
+LazyValueInfoImpl::solveBlockValueBinaryOp(BinaryOperator *BO, BasicBlock *BB) {
assert(BO->getOperand(0)->getType()->isSized() &&
"all operands to binary operators are sized");
if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(BO)) {
@@ -975,7 +979,7 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueBinaryOp(
});
}
-Optional<ValueLatticeElement>
+std::optional<ValueLatticeElement>
LazyValueInfoImpl::solveBlockValueOverflowIntrinsic(WithOverflowInst *WO,
BasicBlock *BB) {
return solveBlockValueBinaryOpImpl(
@@ -984,8 +988,8 @@ LazyValueInfoImpl::solveBlockValueOverflowIntrinsic(WithOverflowInst *WO,
});
}
-Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueIntrinsic(
- IntrinsicInst *II, BasicBlock *BB) {
+std::optional<ValueLatticeElement>
+LazyValueInfoImpl::solveBlockValueIntrinsic(IntrinsicInst *II, BasicBlock *BB) {
if (!ConstantRange::isIntrinsicSupported(II->getIntrinsicID())) {
LLVM_DEBUG(dbgs() << " compute BB '" << BB->getName()
<< "' - unknown intrinsic.\n");
@@ -994,9 +998,9 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueIntrinsic(
SmallVector<ConstantRange, 2> OpRanges;
for (Value *Op : II->args()) {
- Optional<ConstantRange> Range = getRangeFor(Op, II, BB);
+ std::optional<ConstantRange> Range = getRangeFor(Op, II, BB);
if (!Range)
- return None;
+ return std::nullopt;
OpRanges.push_back(*Range);
}
@@ -1004,8 +1008,9 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueIntrinsic(
ConstantRange::intrinsic(II->getIntrinsicID(), OpRanges));
}
-Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueExtractValue(
- ExtractValueInst *EVI, BasicBlock *BB) {
+std::optional<ValueLatticeElement>
+LazyValueInfoImpl::solveBlockValueExtractValue(ExtractValueInst *EVI,
+ BasicBlock *BB) {
if (auto *WO = dyn_cast<WithOverflowInst>(EVI->getAggregateOperand()))
if (EVI->getNumIndices() == 1 && *EVI->idx_begin() == 0)
return solveBlockValueOverflowIntrinsic(WO, BB);
@@ -1161,11 +1166,16 @@ static ValueLatticeElement getValueFromOverflowCondition(
return ValueLatticeElement::getRange(NWR);
}
-static Optional<ValueLatticeElement>
-getValueFromConditionImpl(Value *Val, Value *Cond, bool isTrueDest,
- bool isRevisit,
- SmallDenseMap<Value *, ValueLatticeElement> &Visited,
- SmallVectorImpl<Value *> &Worklist) {
+// Tracks a Value * condition and whether we're interested in it or its inverse
+typedef PointerIntPair<Value *, 1, bool> CondValue;
+
+static std::optional<ValueLatticeElement> getValueFromConditionImpl(
+ Value *Val, CondValue CondVal, bool isRevisit,
+ SmallDenseMap<CondValue, ValueLatticeElement> &Visited,
+ SmallVectorImpl<CondValue> &Worklist) {
+
+ Value *Cond = CondVal.getPointer();
+ bool isTrueDest = CondVal.getInt();
if (!isRevisit) {
if (ICmpInst *ICI = dyn_cast<ICmpInst>(Cond))
return getValueFromICmpCondition(Val, ICI, isTrueDest);
@@ -1176,6 +1186,17 @@ getValueFromConditionImpl(Value *Val, Value *Cond, bool isTrueDest,
return getValueFromOverflowCondition(Val, WO, isTrueDest);
}
+ Value *N;
+ if (match(Cond, m_Not(m_Value(N)))) {
+ CondValue NKey(N, !isTrueDest);
+ auto NV = Visited.find(NKey);
+ if (NV == Visited.end()) {
+ Worklist.push_back(NKey);
+ return std::nullopt;
+ }
+ return NV->second;
+ }
+
Value *L, *R;
bool IsAnd;
if (match(Cond, m_LogicalAnd(m_Value(L), m_Value(R))))
@@ -1185,13 +1206,13 @@ getValueFromConditionImpl(Value *Val, Value *Cond, bool isTrueDest,
else
return ValueLatticeElement::getOverdefined();
- auto LV = Visited.find(L);
- auto RV = Visited.find(R);
+ auto LV = Visited.find(CondValue(L, isTrueDest));
+ auto RV = Visited.find(CondValue(R, isTrueDest));
// if (L && R) -> intersect L and R
- // if (!(L || R)) -> intersect L and R
+ // if (!(L || R)) -> intersect !L and !R
// if (L || R) -> union L and R
- // if (!(L && R)) -> union L and R
+ // if (!(L && R)) -> union !L and !R
if ((isTrueDest ^ IsAnd) && (LV != Visited.end())) {
ValueLatticeElement V = LV->second;
if (V.isOverdefined())
@@ -1205,10 +1226,10 @@ getValueFromConditionImpl(Value *Val, Value *Cond, bool isTrueDest,
if (LV == Visited.end() || RV == Visited.end()) {
assert(!isRevisit);
if (LV == Visited.end())
- Worklist.push_back(L);
+ Worklist.push_back(CondValue(L, isTrueDest));
if (RV == Visited.end())
- Worklist.push_back(R);
- return None;
+ Worklist.push_back(CondValue(R, isTrueDest));
+ return std::nullopt;
}
return intersect(LV->second, RV->second);
@@ -1217,12 +1238,13 @@ getValueFromConditionImpl(Value *Val, Value *Cond, bool isTrueDest,
ValueLatticeElement getValueFromCondition(Value *Val, Value *Cond,
bool isTrueDest) {
assert(Cond && "precondition");
- SmallDenseMap<Value*, ValueLatticeElement> Visited;
- SmallVector<Value *> Worklist;
+ SmallDenseMap<CondValue, ValueLatticeElement> Visited;
+ SmallVector<CondValue> Worklist;
- Worklist.push_back(Cond);
+ CondValue CondKey(Cond, isTrueDest);
+ Worklist.push_back(CondKey);
do {
- Value *CurrentCond = Worklist.back();
+ CondValue CurrentCond = Worklist.back();
// Insert an Overdefined placeholder into the set to prevent
// infinite recursion if there exists IRs that use not
// dominated by its def as in this example:
@@ -1231,15 +1253,15 @@ ValueLatticeElement getValueFromCondition(Value *Val, Value *Cond,
auto Iter =
Visited.try_emplace(CurrentCond, ValueLatticeElement::getOverdefined());
bool isRevisit = !Iter.second;
- Optional<ValueLatticeElement> Result = getValueFromConditionImpl(
- Val, CurrentCond, isTrueDest, isRevisit, Visited, Worklist);
+ std::optional<ValueLatticeElement> Result = getValueFromConditionImpl(
+ Val, CurrentCond, isRevisit, Visited, Worklist);
if (Result) {
Visited[CurrentCond] = *Result;
Worklist.pop_back();
}
} while (!Worklist.empty());
- auto Result = Visited.find(Cond);
+ auto Result = Visited.find(CondKey);
assert(Result != Visited.end());
return Result->second;
}
@@ -1295,7 +1317,7 @@ static ValueLatticeElement constantFoldUser(User *Usr, Value *Op,
/// Compute the value of Val on the edge BBFrom -> BBTo. Returns false if
/// Val is not constrained on the edge. Result is unspecified if return value
/// is false.
-static Optional<ValueLatticeElement> getEdgeValueLocal(Value *Val,
+static std::optional<ValueLatticeElement> getEdgeValueLocal(Value *Val,
BasicBlock *BBFrom,
BasicBlock *BBTo) {
// TODO: Handle more complex conditionals. If (v == 0 || v2 < 1) is false, we
@@ -1352,7 +1374,8 @@ static Optional<ValueLatticeElement> getEdgeValueLocal(Value *Val,
Value *Op = Usr->getOperand(i);
ValueLatticeElement OpLatticeVal =
getValueFromCondition(Op, Condition, isTrueDest);
- if (Optional<APInt> OpConst = OpLatticeVal.asConstantInteger()) {
+ if (std::optional<APInt> OpConst =
+ OpLatticeVal.asConstantInteger()) {
Result = constantFoldUser(Usr, Op, *OpConst, DL);
break;
}
@@ -1370,7 +1393,7 @@ static Optional<ValueLatticeElement> getEdgeValueLocal(Value *Val,
if (SwitchInst *SI = dyn_cast<SwitchInst>(BBFrom->getTerminator())) {
Value *Condition = SI->getCondition();
if (!isa<IntegerType>(Val->getType()))
- return None;
+ return std::nullopt;
bool ValUsesConditionAndMayBeFoldable = false;
if (Condition != Val) {
// Check if Val has Condition as an operand.
@@ -1378,7 +1401,7 @@ static Optional<ValueLatticeElement> getEdgeValueLocal(Value *Val,
ValUsesConditionAndMayBeFoldable = isOperationFoldable(Usr) &&
usesOperand(Usr, Condition);
if (!ValUsesConditionAndMayBeFoldable)
- return None;
+ return std::nullopt;
}
assert((Condition == Val || ValUsesConditionAndMayBeFoldable) &&
"Condition != Val nor Val doesn't use Condition");
@@ -1396,7 +1419,7 @@ static Optional<ValueLatticeElement> getEdgeValueLocal(Value *Val,
ValueLatticeElement EdgeLatticeVal =
constantFoldUser(Usr, Condition, CaseValue, DL);
if (EdgeLatticeVal.isOverdefined())
- return None;
+ return std::nullopt;
EdgeVal = EdgeLatticeVal.getConstantRange();
}
if (DefaultCase) {
@@ -1413,13 +1436,14 @@ static Optional<ValueLatticeElement> getEdgeValueLocal(Value *Val,
}
return ValueLatticeElement::getRange(std::move(EdgesVals));
}
- return None;
+ return std::nullopt;
}
/// Compute the value of Val on the edge BBFrom -> BBTo or the value at
/// the basic block if the edge does not constrain Val.
-Optional<ValueLatticeElement> LazyValueInfoImpl::getEdgeValue(
- Value *Val, BasicBlock *BBFrom, BasicBlock *BBTo, Instruction *CxtI) {
+std::optional<ValueLatticeElement>
+LazyValueInfoImpl::getEdgeValue(Value *Val, BasicBlock *BBFrom,
+ BasicBlock *BBTo, Instruction *CxtI) {
// If already a constant, there is nothing to compute.
if (Constant *VC = dyn_cast<Constant>(Val))
return ValueLatticeElement::get(VC);
@@ -1431,10 +1455,10 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::getEdgeValue(
// Can't get any more precise here
return LocalResult;
- Optional<ValueLatticeElement> OptInBlock =
+ std::optional<ValueLatticeElement> OptInBlock =
getBlockValue(Val, BBFrom, BBFrom->getTerminator());
if (!OptInBlock)
- return None;
+ return std::nullopt;
ValueLatticeElement &InBlock = *OptInBlock;
// We can use the context instruction (generically the ultimate instruction
@@ -1456,7 +1480,7 @@ ValueLatticeElement LazyValueInfoImpl::getValueInBlock(Value *V, BasicBlock *BB,
<< BB->getName() << "'\n");
assert(BlockValueStack.empty() && BlockValueSet.empty());
- Optional<ValueLatticeElement> OptResult = getBlockValue(V, BB, CxtI);
+ std::optional<ValueLatticeElement> OptResult = getBlockValue(V, BB, CxtI);
if (!OptResult) {
solve();
OptResult = getBlockValue(V, BB, CxtI);
@@ -1491,7 +1515,8 @@ getValueOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB,
<< FromBB->getName() << "' to '" << ToBB->getName()
<< "'\n");
- Optional<ValueLatticeElement> Result = getEdgeValue(V, FromBB, ToBB, CxtI);
+ std::optional<ValueLatticeElement> Result =
+ getEdgeValue(V, FromBB, ToBB, CxtI);
if (!Result) {
solve();
Result = getEdgeValue(V, FromBB, ToBB, CxtI);
@@ -1625,6 +1650,48 @@ ConstantRange LazyValueInfo::getConstantRange(Value *V, Instruction *CxtI,
return ConstantRange::getFull(Width);
}
+ConstantRange LazyValueInfo::getConstantRangeAtUse(const Use &U,
+ bool UndefAllowed) {
+ Value *V = U.get();
+ ConstantRange CR =
+ getConstantRange(V, cast<Instruction>(U.getUser()), UndefAllowed);
+
+ // Check whether the only (possibly transitive) use of the value is in a
+ // position where V can be constrained by a select or branch condition.
+ const Use *CurrU = &U;
+ // TODO: Increase limit?
+ const unsigned MaxUsesToInspect = 3;
+ for (unsigned I = 0; I < MaxUsesToInspect; ++I) {
+ std::optional<ValueLatticeElement> CondVal;
+ auto *CurrI = cast<Instruction>(CurrU->getUser());
+ if (auto *SI = dyn_cast<SelectInst>(CurrI)) {
+ if (CurrU->getOperandNo() == 1)
+ CondVal = getValueFromCondition(V, SI->getCondition(), true);
+ else if (CurrU->getOperandNo() == 2)
+ CondVal = getValueFromCondition(V, SI->getCondition(), false);
+ } else if (auto *PHI = dyn_cast<PHINode>(CurrI)) {
+ // TODO: Use non-local query?
+ CondVal =
+ getEdgeValueLocal(V, PHI->getIncomingBlock(*CurrU), PHI->getParent());
+ } else if (!isSafeToSpeculativelyExecute(CurrI)) {
+ // Stop walking if we hit a non-speculatable instruction. Even if the
+ // result is only used under a specific condition, executing the
+ // instruction itself may cause side effects or UB already.
+ break;
+ }
+ if (CondVal && CondVal->isConstantRange())
+ CR = CR.intersectWith(CondVal->getConstantRange());
+
+ // Only follow one-use chain, to allow direct intersection of conditions.
+ // If there are multiple uses, we would have to intersect with the union of
+ // all conditions at different uses.
+ if (!CurrI->hasOneUse())
+ break;
+ CurrU = &*CurrI->use_begin();
+ }
+ return CR;
+}
+
/// 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,
@@ -1859,9 +1926,27 @@ LazyValueInfo::Tristate LazyValueInfo::getPredicateAt(unsigned P, Value *LHS,
return getPredicateAt(CmpInst::getSwappedPredicate(Pred), RHS, C, CxtI,
UseBlockValue);
- // Got two non-Constant values. While we could handle them somewhat,
- // by getting their constant ranges, and applying ConstantRange::icmp(),
- // so far it did not appear to be profitable.
+ // Got two non-Constant values. Try to determine the comparison results based
+ // on the block values of the two operands, e.g. because they have
+ // non-overlapping ranges.
+ if (UseBlockValue) {
+ Module *M = CxtI->getModule();
+ ValueLatticeElement L =
+ getImpl(PImpl, AC, M).getValueInBlock(LHS, CxtI->getParent(), CxtI);
+ if (L.isOverdefined())
+ return LazyValueInfo::Unknown;
+
+ ValueLatticeElement R =
+ getImpl(PImpl, AC, M).getValueInBlock(RHS, CxtI->getParent(), CxtI);
+ Type *Ty = CmpInst::makeCmpResultType(LHS->getType());
+ if (Constant *Res = L.getCompare((CmpInst::Predicate)P, Ty, R,
+ M->getDataLayout())) {
+ if (Res->isNullValue())
+ return LazyValueInfo::False;
+ if (Res->isOneValue())
+ return LazyValueInfo::True;
+ }
+ }
return LazyValueInfo::Unknown;
}