Skip to content

Commit 7de592b

Browse files
committed
[LVI] Move bulk of getConstantRangeAtUse() implementation into Impl (NFC)
Make the layering here similar to all the other methods: LazyValueInfoImpl implements the underlying API returning a ValueLatticeElement, and then LazyValueInfo exposes this as a ConstantRange publicly.
1 parent 1c6b336 commit 7de592b

File tree

1 file changed

+52
-43
lines changed

1 file changed

+52
-43
lines changed

llvm/lib/Analysis/LazyValueInfo.cpp

Lines changed: 52 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,8 @@ class LazyValueInfoImpl {
453453
BasicBlock *ToBB,
454454
Instruction *CxtI = nullptr);
455455

456+
ValueLatticeElement getValueAtUse(const Use &U);
457+
456458
/// Complete flush all previously computed values
457459
void clear() {
458460
TheCache.clear();
@@ -1512,6 +1514,52 @@ getValueOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB,
15121514
return *Result;
15131515
}
15141516

1517+
ValueLatticeElement LazyValueInfoImpl::getValueAtUse(const Use &U) {
1518+
Value *V = U.get();
1519+
auto *CxtI = cast<Instruction>(U.getUser());
1520+
ValueLatticeElement VL = getValueInBlock(V, CxtI->getParent(), CxtI);
1521+
1522+
// Check whether the only (possibly transitive) use of the value is in a
1523+
// position where V can be constrained by a select or branch condition.
1524+
const Use *CurrU = &U;
1525+
// TODO: Increase limit?
1526+
const unsigned MaxUsesToInspect = 3;
1527+
for (unsigned I = 0; I < MaxUsesToInspect; ++I) {
1528+
std::optional<ValueLatticeElement> CondVal;
1529+
auto *CurrI = cast<Instruction>(CurrU->getUser());
1530+
if (auto *SI = dyn_cast<SelectInst>(CurrI)) {
1531+
// If the value is undef, a different value may be chosen in
1532+
// the select condition and at use.
1533+
if (!isGuaranteedNotToBeUndef(SI->getCondition(), AC))
1534+
break;
1535+
if (CurrU->getOperandNo() == 1)
1536+
CondVal = getValueFromCondition(V, SI->getCondition(), true);
1537+
else if (CurrU->getOperandNo() == 2)
1538+
CondVal = getValueFromCondition(V, SI->getCondition(), false);
1539+
} else if (auto *PHI = dyn_cast<PHINode>(CurrI)) {
1540+
// TODO: Use non-local query?
1541+
CondVal =
1542+
getEdgeValueLocal(V, PHI->getIncomingBlock(*CurrU), PHI->getParent());
1543+
}
1544+
if (CondVal)
1545+
VL = intersect(VL, *CondVal);
1546+
1547+
// Only follow one-use chain, to allow direct intersection of conditions.
1548+
// If there are multiple uses, we would have to intersect with the union of
1549+
// all conditions at different uses.
1550+
// Stop walking if we hit a non-speculatable instruction. Even if the
1551+
// result is only used under a specific condition, executing the
1552+
// instruction itself may cause side effects or UB already.
1553+
// This also disallows looking through phi nodes: If the phi node is part
1554+
// of a cycle, we might end up reasoning about values from different cycle
1555+
// iterations (PR60629).
1556+
if (!CurrI->hasOneUse() || !isSafeToSpeculativelyExecute(CurrI))
1557+
break;
1558+
CurrU = &*CurrI->use_begin();
1559+
}
1560+
return VL;
1561+
}
1562+
15151563
void LazyValueInfoImpl::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc,
15161564
BasicBlock *NewSucc) {
15171565
TheCache.threadEdgeImpl(OldSucc, NewSucc);
@@ -1633,49 +1681,10 @@ ConstantRange LazyValueInfo::getConstantRange(Value *V, Instruction *CxtI,
16331681

16341682
ConstantRange LazyValueInfo::getConstantRangeAtUse(const Use &U,
16351683
bool UndefAllowed) {
1636-
Value *V = U.get();
1637-
ConstantRange CR =
1638-
getConstantRange(V, cast<Instruction>(U.getUser()), UndefAllowed);
1639-
1640-
// Check whether the only (possibly transitive) use of the value is in a
1641-
// position where V can be constrained by a select or branch condition.
1642-
const Use *CurrU = &U;
1643-
// TODO: Increase limit?
1644-
const unsigned MaxUsesToInspect = 3;
1645-
for (unsigned I = 0; I < MaxUsesToInspect; ++I) {
1646-
std::optional<ValueLatticeElement> CondVal;
1647-
auto *CurrI = cast<Instruction>(CurrU->getUser());
1648-
if (auto *SI = dyn_cast<SelectInst>(CurrI)) {
1649-
// If the value is undef, a different value may be chosen in
1650-
// the select condition and at use.
1651-
if (!isGuaranteedNotToBeUndef(SI->getCondition(), AC))
1652-
break;
1653-
if (CurrU->getOperandNo() == 1)
1654-
CondVal = getValueFromCondition(V, SI->getCondition(), true);
1655-
else if (CurrU->getOperandNo() == 2)
1656-
CondVal = getValueFromCondition(V, SI->getCondition(), false);
1657-
} else if (auto *PHI = dyn_cast<PHINode>(CurrI)) {
1658-
// TODO: Use non-local query?
1659-
CondVal =
1660-
getEdgeValueLocal(V, PHI->getIncomingBlock(*CurrU), PHI->getParent());
1661-
}
1662-
if (CondVal && CondVal->isConstantRange())
1663-
CR = CR.intersectWith(CondVal->getConstantRange());
1664-
1665-
// Only follow one-use chain, to allow direct intersection of conditions.
1666-
// If there are multiple uses, we would have to intersect with the union of
1667-
// all conditions at different uses.
1668-
// Stop walking if we hit a non-speculatable instruction. Even if the
1669-
// result is only used under a specific condition, executing the
1670-
// instruction itself may cause side effects or UB already.
1671-
// This also disallows looking through phi nodes: If the phi node is part
1672-
// of a cycle, we might end up reasoning about values from different cycle
1673-
// iterations (PR60629).
1674-
if (!CurrI->hasOneUse() || !isSafeToSpeculativelyExecute(CurrI))
1675-
break;
1676-
CurrU = &*CurrI->use_begin();
1677-
}
1678-
return CR;
1684+
auto *Inst = cast<Instruction>(U.getUser());
1685+
ValueLatticeElement Result =
1686+
getOrCreateImpl(Inst->getModule()).getValueAtUse(U);
1687+
return toConstantRange(Result, U->getType(), UndefAllowed);
16791688
}
16801689

16811690
/// Determine whether the specified value is known to be a

0 commit comments

Comments
 (0)