mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
[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
This commit is contained in:
parent
e702056af0
commit
45b4219826
@ -1151,20 +1151,20 @@ static ValueLatticeElement getValueFromOverflowCondition(
|
|||||||
return ValueLatticeElement::getRange(NWR);
|
return ValueLatticeElement::getRange(NWR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ValueLatticeElement
|
static Optional<ValueLatticeElement>
|
||||||
getValueFromCondition(Value *Val, Value *Cond, bool isTrueDest,
|
|
||||||
SmallDenseMap<Value*, ValueLatticeElement> &Visited);
|
|
||||||
|
|
||||||
static ValueLatticeElement
|
|
||||||
getValueFromConditionImpl(Value *Val, Value *Cond, bool isTrueDest,
|
getValueFromConditionImpl(Value *Val, Value *Cond, bool isTrueDest,
|
||||||
SmallDenseMap<Value*, ValueLatticeElement> &Visited) {
|
bool isRevisit,
|
||||||
if (ICmpInst *ICI = dyn_cast<ICmpInst>(Cond))
|
SmallDenseMap<Value *, ValueLatticeElement> &Visited,
|
||||||
return getValueFromICmpCondition(Val, ICI, isTrueDest);
|
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 *EVI = dyn_cast<ExtractValueInst>(Cond))
|
||||||
if (auto *WO = dyn_cast<WithOverflowInst>(EVI->getAggregateOperand()))
|
if (auto *WO = dyn_cast<WithOverflowInst>(EVI->getAggregateOperand()))
|
||||||
if (EVI->getNumIndices() == 1 && *EVI->idx_begin() == 1)
|
if (EVI->getNumIndices() == 1 && *EVI->idx_begin() == 1)
|
||||||
return getValueFromOverflowCondition(Val, WO, isTrueDest);
|
return getValueFromOverflowCondition(Val, WO, isTrueDest);
|
||||||
|
}
|
||||||
|
|
||||||
Value *L, *R;
|
Value *L, *R;
|
||||||
bool IsAnd;
|
bool IsAnd;
|
||||||
@ -1175,44 +1175,63 @@ getValueFromConditionImpl(Value *Val, Value *Cond, bool isTrueDest,
|
|||||||
else
|
else
|
||||||
return ValueLatticeElement::getOverdefined();
|
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)) -> 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 (!(L && R)) -> union L and R
|
||||||
if (isTrueDest ^ IsAnd) {
|
if ((isTrueDest ^ IsAnd) && (LV != Visited.end())) {
|
||||||
ValueLatticeElement V = getValueFromCondition(Val, L, isTrueDest, Visited);
|
ValueLatticeElement V = LV->second;
|
||||||
if (V.isOverdefined())
|
if (V.isOverdefined())
|
||||||
return V;
|
return V;
|
||||||
V.mergeIn(getValueFromCondition(Val, R, isTrueDest, Visited));
|
if (RV != Visited.end()) {
|
||||||
return V;
|
V.mergeIn(RV->second);
|
||||||
|
return V;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return intersect(getValueFromCondition(Val, L, isTrueDest, Visited),
|
if (LV == Visited.end() || RV == Visited.end()) {
|
||||||
getValueFromCondition(Val, R, isTrueDest, Visited));
|
assert(!isRevisit);
|
||||||
}
|
if (LV == Visited.end())
|
||||||
|
Worklist.push_back(L);
|
||||||
|
if (RV == Visited.end())
|
||||||
|
Worklist.push_back(R);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
static ValueLatticeElement
|
return intersect(LV->second, RV->second);
|
||||||
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();
|
|
||||||
|
|
||||||
auto Result = getValueFromConditionImpl(Val, Cond, isTrueDest, Visited);
|
|
||||||
Visited[Cond] = Result;
|
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueLatticeElement getValueFromCondition(Value *Val, Value *Cond,
|
ValueLatticeElement getValueFromCondition(Value *Val, Value *Cond,
|
||||||
bool isTrueDest) {
|
bool isTrueDest) {
|
||||||
assert(Cond && "precondition");
|
assert(Cond && "precondition");
|
||||||
SmallDenseMap<Value*, ValueLatticeElement> Visited;
|
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.
|
// Return true if Usr has Op as an operand, otherwise false.
|
||||||
|
Loading…
Reference in New Issue
Block a user