[llvm] ae266e7 - [LVI] Remove recursion from getValueForCondition (NFCI)
Carl Ritson via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 23 17:58:55 PDT 2021
Author: Carl Ritson
Date: 2021-06-24T09:58:22+09:00
New Revision: ae266e743c9182ebd9702ccea2afb16f470013db
URL: https://github.com/llvm/llvm-project/commit/ae266e743c9182ebd9702ccea2afb16f470013db
DIFF: https://github.com/llvm/llvm-project/commit/ae266e743c9182ebd9702ccea2afb16f470013db.diff
LOG: [LVI] Remove recursion from getValueForCondition (NFCI)
Convert getValueForCondition to a worklist model instead of using
recursion.
In pathological cases getValueForCondition recurses heavily.
Stack frames are quite expensive on x86-64, and some operating
systems (e.g. Windows) have relatively low stack size limits.
Using a worklist avoids potential failures from stack overflow.
Differential Revision: https://reviews.llvm.org/D104191
Added:
Modified:
llvm/lib/Analysis/LazyValueInfo.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index 83d83f45c972..1dababafb8a6 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -1151,20 +1151,20 @@ static ValueLatticeElement getValueFromOverflowCondition(
return ValueLatticeElement::getRange(NWR);
}
-static ValueLatticeElement
-getValueFromCondition(Value *Val, Value *Cond, bool isTrueDest,
- SmallDenseMap<Value*, ValueLatticeElement> &Visited);
-
-static ValueLatticeElement
+static Optional<ValueLatticeElement>
getValueFromConditionImpl(Value *Val, Value *Cond, bool isTrueDest,
- SmallDenseMap<Value*, ValueLatticeElement> &Visited) {
- if (ICmpInst *ICI = dyn_cast<ICmpInst>(Cond))
- return getValueFromICmpCondition(Val, ICI, isTrueDest);
-
- if (auto *EVI = dyn_cast<ExtractValueInst>(Cond))
- if (auto *WO = dyn_cast<WithOverflowInst>(EVI->getAggregateOperand()))
- if (EVI->getNumIndices() == 1 && *EVI->idx_begin() == 1)
- return getValueFromOverflowCondition(Val, WO, isTrueDest);
+ bool isRevisit,
+ SmallDenseMap<Value *, ValueLatticeElement> &Visited,
+ SmallVectorImpl<Value *> &Worklist) {
+ if (!isRevisit) {
+ if (ICmpInst *ICI = dyn_cast<ICmpInst>(Cond))
+ return getValueFromICmpCondition(Val, ICI, isTrueDest);
+
+ if (auto *EVI = dyn_cast<ExtractValueInst>(Cond))
+ if (auto *WO = dyn_cast<WithOverflowInst>(EVI->getAggregateOperand()))
+ if (EVI->getNumIndices() == 1 && *EVI->idx_begin() == 1)
+ return getValueFromOverflowCondition(Val, WO, isTrueDest);
+ }
Value *L, *R;
bool IsAnd;
@@ -1175,44 +1175,63 @@ getValueFromConditionImpl(Value *Val, Value *Cond, bool isTrueDest,
else
return ValueLatticeElement::getOverdefined();
+ auto LV = Visited.find(L);
+ auto RV = Visited.find(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 (isTrueDest ^ IsAnd) {
- ValueLatticeElement V = getValueFromCondition(Val, L, isTrueDest, Visited);
+ if ((isTrueDest ^ IsAnd) && (LV != Visited.end())) {
+ ValueLatticeElement V = LV->second;
if (V.isOverdefined())
return V;
- V.mergeIn(getValueFromCondition(Val, R, isTrueDest, Visited));
- return V;
+ if (RV != Visited.end()) {
+ V.mergeIn(RV->second);
+ return V;
+ }
}
- return intersect(getValueFromCondition(Val, L, isTrueDest, Visited),
- getValueFromCondition(Val, R, isTrueDest, Visited));
-}
-
-static ValueLatticeElement
-getValueFromCondition(Value *Val, Value *Cond, bool isTrueDest,
- SmallDenseMap<Value*, ValueLatticeElement> &Visited) {
- // 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:
- // "%tmp3 = or i1 undef, %tmp4"
- // "%tmp4 = or i1 undef, %tmp3"
- auto Iter = Visited.try_emplace(Cond, ValueLatticeElement::getOverdefined());
- if (!Iter.second)
- return Iter.first->getSecond();
+ if (LV == Visited.end() || RV == Visited.end()) {
+ assert(!isRevisit);
+ if (LV == Visited.end())
+ Worklist.push_back(L);
+ if (RV == Visited.end())
+ Worklist.push_back(R);
+ return None;
+ }
- auto Result = getValueFromConditionImpl(Val, Cond, isTrueDest, Visited);
- Visited[Cond] = Result;
- return Result;
+ return intersect(LV->second, RV->second);
}
ValueLatticeElement getValueFromCondition(Value *Val, Value *Cond,
bool isTrueDest) {
assert(Cond && "precondition");
SmallDenseMap<Value*, ValueLatticeElement> Visited;
- return getValueFromCondition(Val, Cond, isTrueDest, Visited);
+ SmallVector<Value *> Worklist;
+
+ Worklist.push_back(Cond);
+ do {
+ Value *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:
+ // "%tmp3 = or i1 undef, %tmp4"
+ // "%tmp4 = or i1 undef, %tmp3"
+ auto Iter =
+ Visited.try_emplace(CurrentCond, ValueLatticeElement::getOverdefined());
+ bool isRevisit = !Iter.second;
+ Optional<ValueLatticeElement> Result = getValueFromConditionImpl(
+ Val, CurrentCond, isTrueDest, isRevisit, Visited, Worklist);
+ if (Result) {
+ Visited[CurrentCond] = *Result;
+ Worklist.pop_back();
+ }
+ } while (!Worklist.empty());
+
+ auto Result = Visited.find(Cond);
+ assert(Result != Visited.end());
+ return Result->second;
}
// Return true if Usr has Op as an operand, otherwise false.
More information about the llvm-commits
mailing list