Skip to content

Commit bb310b3

Browse files
committed
Recommit "[SCCP] Remove forcedconstant, go to overdefined instead"
This version includes a fix for a set of crashes caused by marking values depending on a yet unknown & tracked call as overdefined. In some cases, we would later discover that the call has a constant result and try to mark a user of it as constant, although it was already marked as overdefined. Most instruction handlers bail out early if the instruction is already overdefined. But that is not necessary for CastInsts for example. By skipping values that depend on skipped calls, we resolve the crashes and also improve the precision in some cases (see resolvedundefsin-tracked-fn.ll). Note that we may not skip PHI nodes that may depend on a skipped call, but they can be safely marked as overdefined, as we bail out early if the PHI node is overdefined. This reverts the revert commit a74b31a3e9cd844c7ce2087978568e3f5ec8519.
1 parent 5bb4954 commit bb310b3

File tree

14 files changed

+648
-349
lines changed

14 files changed

+648
-349
lines changed

llvm/lib/Transforms/Scalar/SCCP.cpp

Lines changed: 28 additions & 235 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,13 @@ class LatticeVal {
8585
/// constant - This LLVM Value has a specific constant value.
8686
constant,
8787

88-
/// forcedconstant - This LLVM Value was thought to be undef until
89-
/// ResolvedUndefsIn. This is treated just like 'constant', but if merged
90-
/// with another (different) constant, it goes to overdefined, instead of
91-
/// asserting.
92-
forcedconstant,
93-
9488
/// overdefined - This instruction is not known to be constant, and we know
9589
/// it has a value.
9690
overdefined
9791
};
9892

9993
/// Val: This stores the current lattice value along with the Constant* for
100-
/// the constant if this is a 'constant' or 'forcedconstant' value.
94+
/// the constant if this is a 'constant' value.
10195
PointerIntPair<Constant *, 2, LatticeValueTy> Val;
10296

10397
LatticeValueTy getLatticeValue() const {
@@ -109,9 +103,7 @@ class LatticeVal {
109103

110104
bool isUnknown() const { return getLatticeValue() == unknown; }
111105

112-
bool isConstant() const {
113-
return getLatticeValue() == constant || getLatticeValue() == forcedconstant;
114-
}
106+
bool isConstant() const { return getLatticeValue() == constant; }
115107

116108
bool isOverdefined() const { return getLatticeValue() == overdefined; }
117109

@@ -131,26 +123,15 @@ class LatticeVal {
131123

132124
/// markConstant - Return true if this is a change in status.
133125
bool markConstant(Constant *V) {
134-
if (getLatticeValue() == constant) { // Constant but not forcedconstant.
126+
if (getLatticeValue() == constant) { // Constant
135127
assert(getConstant() == V && "Marking constant with different value");
136128
return false;
137129
}
138130

139-
if (isUnknown()) {
140-
Val.setInt(constant);
141-
assert(V && "Marking constant with NULL");
142-
Val.setPointer(V);
143-
} else {
144-
assert(getLatticeValue() == forcedconstant &&
145-
"Cannot move from overdefined to constant!");
146-
// Stay at forcedconstant if the constant is the same.
147-
if (V == getConstant()) return false;
148-
149-
// Otherwise, we go to overdefined. Assumptions made based on the
150-
// forced value are possibly wrong. Assuming this is another constant
151-
// could expose a contradiction.
152-
Val.setInt(overdefined);
153-
}
131+
assert(isUnknown());
132+
Val.setInt(constant);
133+
assert(V && "Marking constant with NULL");
134+
Val.setPointer(V);
154135
return true;
155136
}
156137

@@ -170,12 +151,6 @@ class LatticeVal {
170151
return nullptr;
171152
}
172153

173-
void markForcedConstant(Constant *V) {
174-
assert(isUnknown() && "Can't force a defined value!");
175-
Val.setInt(forcedconstant);
176-
Val.setPointer(V);
177-
}
178-
179154
ValueLatticeElement toValueLattice() const {
180155
if (isOverdefined())
181156
return ValueLatticeElement::getOverdefined();
@@ -421,7 +396,7 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
421396
}
422397

423398
private:
424-
// pushToWorkList - Helper for markConstant/markForcedConstant/markOverdefined
399+
// pushToWorkList - Helper for markConstant/markOverdefined
425400
void pushToWorkList(LatticeVal &IV, Value *V) {
426401
if (IV.isOverdefined())
427402
return OverdefinedInstWorkList.push_back(V);
@@ -443,14 +418,6 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
443418
return markConstant(ValueState[V], V, C);
444419
}
445420

446-
void markForcedConstant(Value *V, Constant *C) {
447-
assert(!V->getType()->isStructTy() && "structs should use mergeInValue");
448-
LatticeVal &IV = ValueState[V];
449-
IV.markForcedConstant(C);
450-
LLVM_DEBUG(dbgs() << "markForcedConstant: " << *C << ": " << *V << '\n');
451-
pushToWorkList(IV, V);
452-
}
453-
454421
// markOverdefined - Make a value be marked as "overdefined". If the
455422
// value is not already overdefined, add it to the overdefined instruction
456423
// work list so that the users of the instruction are updated later.
@@ -996,8 +963,6 @@ void SCCPSolver::visitUnaryOperator(Instruction &I) {
996963
LatticeVal V0State = getValueState(I.getOperand(0));
997964

998965
LatticeVal &IV = ValueState[&I];
999-
if (IV.isOverdefined()) return;
1000-
1001966
if (V0State.isConstant()) {
1002967
Constant *C = ConstantExpr::get(I.getOpcode(), V0State.getConstant());
1003968

@@ -1032,8 +997,10 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
1032997
}
1033998

1034999
// If something is undef, wait for it to resolve.
1035-
if (!V1State.isOverdefined() && !V2State.isOverdefined())
1000+
if (!V1State.isOverdefined() && !V2State.isOverdefined()) {
1001+
10361002
return;
1003+
}
10371004

10381005
// Otherwise, one of our operands is overdefined. Try to produce something
10391006
// better than overdefined with some tricks.
@@ -1054,7 +1021,6 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
10541021
NonOverdefVal = &V1State;
10551022
else if (!V2State.isOverdefined())
10561023
NonOverdefVal = &V2State;
1057-
10581024
if (NonOverdefVal) {
10591025
if (NonOverdefVal->isUnknown())
10601026
return;
@@ -1174,7 +1140,6 @@ void SCCPSolver::visitLoadInst(LoadInst &I) {
11741140
if (PtrVal.isUnknown()) return; // The pointer is not resolved yet!
11751141

11761142
LatticeVal &IV = ValueState[&I];
1177-
if (IV.isOverdefined()) return;
11781143

11791144
if (!PtrVal.isConstant() || I.isVolatile())
11801145
return (void)markOverdefined(IV, &I);
@@ -1449,11 +1414,11 @@ void SCCPSolver::Solve() {
14491414
/// constraints on the condition of the branch, as that would impact other users
14501415
/// of the value.
14511416
///
1452-
/// This scan also checks for values that use undefs, whose results are actually
1453-
/// defined. For example, 'zext i8 undef to i32' should produce all zeros
1454-
/// conservatively, as "(zext i8 X -> i32) & 0xFF00" must always return zero,
1455-
/// even if X isn't defined.
1417+
/// This scan also checks for values that use undefs. It conservatively marks
1418+
/// them as overdefined.
14561419
bool SCCPSolver::ResolvedUndefsIn(Function &F) {
1420+
// Keep track of values that dependent on an yet unknown tracked function call. It only makes sense to resolve them once the call is resolved.
1421+
SmallPtrSet<Value *, 8> DependsOnSkipped;
14571422
for (BasicBlock &BB : F) {
14581423
if (!BBExecutable.count(&BB))
14591424
continue;
@@ -1468,14 +1433,15 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
14681433
// Tracked calls must never be marked overdefined in ResolvedUndefsIn.
14691434
if (CallSite CS = CallSite(&I))
14701435
if (Function *F = CS.getCalledFunction())
1471-
if (MRVFunctionsTracked.count(F))
1436+
if (MRVFunctionsTracked.count(F)) {
1437+
DependsOnSkipped.insert(&I);
14721438
continue;
1439+
}
14731440

14741441
// extractvalue and insertvalue don't need to be marked; they are
14751442
// tracked as precisely as their operands.
14761443
if (isa<ExtractValueInst>(I) || isa<InsertValueInst>(I))
14771444
continue;
1478-
14791445
// Send the results of everything else to overdefined. We could be
14801446
// more precise than this but it isn't worth bothering.
14811447
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
@@ -1495,195 +1461,22 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
14951461
// 2. It could be constant-foldable.
14961462
// Because of the way we solve return values, tracked calls must
14971463
// never be marked overdefined in ResolvedUndefsIn.
1498-
if (CallSite CS = CallSite(&I)) {
1464+
if (CallSite CS = CallSite(&I))
14991465
if (Function *F = CS.getCalledFunction())
1500-
if (TrackedRetVals.count(F))
1466+
if (TrackedRetVals.count(F)) {
1467+
DependsOnSkipped.insert(&I);
15011468
continue;
1469+
}
15021470

1503-
// If the call is constant-foldable, we mark it overdefined because
1504-
// we do not know what return values are valid.
1505-
markOverdefined(&I);
1506-
return true;
1507-
}
1508-
1509-
// extractvalue is safe; check here because the argument is a struct.
1510-
if (isa<ExtractValueInst>(I))
1471+
// Skip instructions that depend on results of calls we skipped earlier. Otherwise we might mark I as overdefined to early when we would end up discovering a constant value for I, if the call later resolves to a constant.
1472+
if (any_of(I.operands(), [&DependsOnSkipped](Value *V) {
1473+
return DependsOnSkipped.find(V) != DependsOnSkipped.end(); })) {
1474+
DependsOnSkipped.insert(&I);
15111475
continue;
1512-
1513-
// Compute the operand LatticeVals, for convenience below.
1514-
// Anything taking a struct is conservatively assumed to require
1515-
// overdefined markings.
1516-
if (I.getOperand(0)->getType()->isStructTy()) {
1517-
markOverdefined(&I);
1518-
return true;
1519-
}
1520-
LatticeVal Op0LV = getValueState(I.getOperand(0));
1521-
LatticeVal Op1LV;
1522-
if (I.getNumOperands() == 2) {
1523-
if (I.getOperand(1)->getType()->isStructTy()) {
1524-
markOverdefined(&I);
1525-
return true;
1526-
}
1527-
1528-
Op1LV = getValueState(I.getOperand(1));
15291476
}
1530-
// If this is an instructions whose result is defined even if the input is
1531-
// not fully defined, propagate the information.
1532-
Type *ITy = I.getType();
1533-
switch (I.getOpcode()) {
1534-
case Instruction::Add:
1535-
case Instruction::Sub:
1536-
case Instruction::Trunc:
1537-
case Instruction::FPTrunc:
1538-
case Instruction::BitCast:
1539-
break; // Any undef -> undef
1540-
case Instruction::FSub:
1541-
case Instruction::FAdd:
1542-
case Instruction::FMul:
1543-
case Instruction::FDiv:
1544-
case Instruction::FRem:
1545-
// Floating-point binary operation: be conservative.
1546-
if (Op0LV.isUnknown() && Op1LV.isUnknown())
1547-
markForcedConstant(&I, Constant::getNullValue(ITy));
1548-
else
1549-
markOverdefined(&I);
1550-
return true;
1551-
case Instruction::FNeg:
1552-
break; // fneg undef -> undef
1553-
case Instruction::ZExt:
1554-
case Instruction::SExt:
1555-
case Instruction::FPToUI:
1556-
case Instruction::FPToSI:
1557-
case Instruction::FPExt:
1558-
case Instruction::PtrToInt:
1559-
case Instruction::IntToPtr:
1560-
case Instruction::SIToFP:
1561-
case Instruction::UIToFP:
1562-
// undef -> 0; some outputs are impossible
1563-
markForcedConstant(&I, Constant::getNullValue(ITy));
1564-
return true;
1565-
case Instruction::Mul:
1566-
case Instruction::And:
1567-
// Both operands undef -> undef
1568-
if (Op0LV.isUnknown() && Op1LV.isUnknown())
1569-
break;
1570-
// undef * X -> 0. X could be zero.
1571-
// undef & X -> 0. X could be zero.
1572-
markForcedConstant(&I, Constant::getNullValue(ITy));
1573-
return true;
1574-
case Instruction::Or:
1575-
// Both operands undef -> undef
1576-
if (Op0LV.isUnknown() && Op1LV.isUnknown())
1577-
break;
1578-
// undef | X -> -1. X could be -1.
1579-
markForcedConstant(&I, Constant::getAllOnesValue(ITy));
1580-
return true;
1581-
case Instruction::Xor:
1582-
// undef ^ undef -> 0; strictly speaking, this is not strictly
1583-
// necessary, but we try to be nice to people who expect this
1584-
// behavior in simple cases
1585-
if (Op0LV.isUnknown() && Op1LV.isUnknown()) {
1586-
markForcedConstant(&I, Constant::getNullValue(ITy));
1587-
return true;
1588-
}
1589-
// undef ^ X -> undef
1590-
break;
1591-
case Instruction::SDiv:
1592-
case Instruction::UDiv:
1593-
case Instruction::SRem:
1594-
case Instruction::URem:
1595-
// X / undef -> undef. No change.
1596-
// X % undef -> undef. No change.
1597-
if (Op1LV.isUnknown()) break;
1598-
1599-
// X / 0 -> undef. No change.
1600-
// X % 0 -> undef. No change.
1601-
if (Op1LV.isConstant() && Op1LV.getConstant()->isZeroValue())
1602-
break;
1603-
1604-
// undef / X -> 0. X could be maxint.
1605-
// undef % X -> 0. X could be 1.
1606-
markForcedConstant(&I, Constant::getNullValue(ITy));
1607-
return true;
1608-
case Instruction::AShr:
1609-
// X >>a undef -> undef.
1610-
if (Op1LV.isUnknown()) break;
1611-
1612-
// Shifting by the bitwidth or more is undefined.
1613-
if (Op1LV.isConstant()) {
1614-
if (auto *ShiftAmt = Op1LV.getConstantInt())
1615-
if (ShiftAmt->getLimitedValue() >=
1616-
ShiftAmt->getType()->getScalarSizeInBits())
1617-
break;
1618-
}
16191477

1620-
// undef >>a X -> 0
1621-
markForcedConstant(&I, Constant::getNullValue(ITy));
1622-
return true;
1623-
case Instruction::LShr:
1624-
case Instruction::Shl:
1625-
// X << undef -> undef.
1626-
// X >> undef -> undef.
1627-
if (Op1LV.isUnknown()) break;
1628-
1629-
// Shifting by the bitwidth or more is undefined.
1630-
if (Op1LV.isConstant()) {
1631-
if (auto *ShiftAmt = Op1LV.getConstantInt())
1632-
if (ShiftAmt->getLimitedValue() >=
1633-
ShiftAmt->getType()->getScalarSizeInBits())
1634-
break;
1635-
}
1636-
1637-
// undef << X -> 0
1638-
// undef >> X -> 0
1639-
markForcedConstant(&I, Constant::getNullValue(ITy));
1640-
return true;
1641-
case Instruction::Select:
1642-
Op1LV = getValueState(I.getOperand(1));
1643-
// undef ? X : Y -> X or Y. There could be commonality between X/Y.
1644-
if (Op0LV.isUnknown()) {
1645-
if (!Op1LV.isConstant()) // Pick the constant one if there is any.
1646-
Op1LV = getValueState(I.getOperand(2));
1647-
} else if (Op1LV.isUnknown()) {
1648-
// c ? undef : undef -> undef. No change.
1649-
Op1LV = getValueState(I.getOperand(2));
1650-
if (Op1LV.isUnknown())
1651-
break;
1652-
// Otherwise, c ? undef : x -> x.
1653-
} else {
1654-
// Leave Op1LV as Operand(1)'s LatticeValue.
1655-
}
1656-
1657-
if (Op1LV.isConstant())
1658-
markForcedConstant(&I, Op1LV.getConstant());
1659-
else
1660-
markOverdefined(&I);
1661-
return true;
1662-
case Instruction::Load:
1663-
// A load here means one of two things: a load of undef from a global,
1664-
// a load from an unknown pointer. Either way, having it return undef
1665-
// is okay.
1666-
break;
1667-
case Instruction::ICmp:
1668-
// X == undef -> undef. Other comparisons get more complicated.
1669-
Op0LV = getValueState(I.getOperand(0));
1670-
Op1LV = getValueState(I.getOperand(1));
1671-
1672-
if ((Op0LV.isUnknown() || Op1LV.isUnknown()) &&
1673-
cast<ICmpInst>(&I)->isEquality())
1674-
break;
1675-
markOverdefined(&I);
1676-
return true;
1677-
case Instruction::Call:
1678-
case Instruction::Invoke:
1679-
case Instruction::CallBr:
1680-
llvm_unreachable("Call-like instructions should have be handled early");
1681-
default:
1682-
// If we don't know what should happen here, conservatively mark it
1683-
// overdefined.
1684-
markOverdefined(&I);
1685-
return true;
1686-
}
1478+
markOverdefined(&I);
1479+
return true;
16871480
}
16881481

16891482
// Check to see if we have a branch or switch on an undefined value. If so

0 commit comments

Comments
 (0)