namespace {
-// Use ValueLatticeElement as LatticeVal.
-using LatticeVal = ValueLatticeElement;
-
// Helper to check if \p LV is either a constant or a constant
// range with a single element. This should cover exactly the same cases as the
-// old LatticeVal::isConstant() and is intended to be used in the transition
-// from LatticeVal to LatticeValueElement.
-bool isConstant(const LatticeVal &LV) {
+// old ValueLatticeElement::isConstant() and is intended to be used in the
+// transition to ValueLatticeElement.
+bool isConstant(const ValueLatticeElement &LV) {
return LV.isConstant() ||
(LV.isConstantRange() && LV.getConstantRange().isSingleElement());
}
// Helper to check if \p LV is either overdefined or a constant range with more
// than a single element. This should cover exactly the same cases as the old
-// LatticeVal::isOverdefined() and is intended to be used in the transition from
-// LatticeVal to LatticeValueElement.
-bool isOverdefined(const LatticeVal &LV) {
+// ValueLatticeElement::isOverdefined() and is intended to be used in the
+// transition to ValueLatticeElement.
+bool isOverdefined(const ValueLatticeElement &LV) {
return LV.isOverdefined() ||
(LV.isConstantRange() && !LV.getConstantRange().isSingleElement());
}
const DataLayout &DL;
std::function<const TargetLibraryInfo &(Function &)> GetTLI;
SmallPtrSet<BasicBlock *, 8> BBExecutable; // The BBs that are executable.
- DenseMap<Value *, LatticeVal> ValueState; // The state each value is in.
+ DenseMap<Value *, ValueLatticeElement>
+ ValueState; // The state each value is in.
/// StructValueState - This maintains ValueState for values that have
/// StructType, for example for formal arguments, calls, insertelement, etc.
- DenseMap<std::pair<Value *, unsigned>, LatticeVal> StructValueState;
+ DenseMap<std::pair<Value *, unsigned>, ValueLatticeElement> StructValueState;
/// GlobalValue - If we are tracking any values for the contents of a global
/// variable, we keep a mapping from the constant accessor to the element of
/// the global, to the currently known value. If the value becomes
/// overdefined, it's entry is simply removed from this map.
- DenseMap<GlobalVariable *, LatticeVal> TrackedGlobals;
+ DenseMap<GlobalVariable *, ValueLatticeElement> TrackedGlobals;
/// TrackedRetVals - If we are tracking arguments into and the return
/// value out of a function, it will have an entry in this map, indicating
/// what the known return value for the function is.
- MapVector<Function *, LatticeVal> TrackedRetVals;
+ MapVector<Function *, ValueLatticeElement> TrackedRetVals;
/// TrackedMultipleRetVals - Same as TrackedRetVals, but used for functions
/// that return multiple values.
- MapVector<std::pair<Function *, unsigned>, LatticeVal> TrackedMultipleRetVals;
+ MapVector<std::pair<Function *, unsigned>, ValueLatticeElement>
+ TrackedMultipleRetVals;
/// MRVFunctionsTracked - Each function in TrackedMultipleRetVals is
/// represented here for efficient lookup.
void TrackValueOfGlobalVariable(GlobalVariable *GV) {
// We only track the contents of scalar globals.
if (GV->getValueType()->isSingleValueType()) {
- LatticeVal &IV = TrackedGlobals[GV];
+ ValueLatticeElement &IV = TrackedGlobals[GV];
if (!isa<UndefValue>(GV->getInitializer()))
IV.markConstant(GV->getInitializer());
}
if (auto *STy = dyn_cast<StructType>(F->getReturnType())) {
MRVFunctionsTracked.insert(F);
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
- TrackedMultipleRetVals.insert(std::make_pair(std::make_pair(F, i),
- LatticeVal()));
+ TrackedMultipleRetVals.insert(
+ std::make_pair(std::make_pair(F, i), ValueLatticeElement()));
} else
- TrackedRetVals.insert(std::make_pair(F, LatticeVal()));
+ TrackedRetVals.insert(std::make_pair(F, ValueLatticeElement()));
}
/// AddMustTailCallee - If the SCCP solver finds that this function is called
// block to the 'To' basic block is currently feasible.
bool isEdgeFeasible(BasicBlock *From, BasicBlock *To);
- std::vector<LatticeVal> getStructLatticeValueFor(Value *V) const {
- std::vector<LatticeVal> StructValues;
+ std::vector<ValueLatticeElement> getStructLatticeValueFor(Value *V) const {
+ std::vector<ValueLatticeElement> StructValues;
auto *STy = dyn_cast<StructType>(V->getType());
assert(STy && "getStructLatticeValueFor() can be called only on structs");
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
return StructValues;
}
- const LatticeVal &getLatticeValueFor(Value *V) const {
+ const ValueLatticeElement &getLatticeValueFor(Value *V) const {
assert(!V->getType()->isStructTy() &&
"Should use getStructLatticeValueFor");
- DenseMap<Value *, LatticeVal>::const_iterator I = ValueState.find(V);
+ DenseMap<Value *, ValueLatticeElement>::const_iterator I =
+ ValueState.find(V);
assert(I != ValueState.end() &&
"V not found in ValueState nor Paramstate map!");
return I->second;
}
/// getTrackedRetVals - Get the inferred return value map.
- const MapVector<Function*, LatticeVal> &getTrackedRetVals() {
+ const MapVector<Function *, ValueLatticeElement> &getTrackedRetVals() {
return TrackedRetVals;
}
/// getTrackedGlobals - Get and return the set of inferred initializers for
/// global variables.
- const DenseMap<GlobalVariable*, LatticeVal> &getTrackedGlobals() {
+ const DenseMap<GlobalVariable *, ValueLatticeElement> &getTrackedGlobals() {
return TrackedGlobals;
}
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
const auto &It = TrackedMultipleRetVals.find(std::make_pair(F, i));
assert(It != TrackedMultipleRetVals.end());
- LatticeVal LV = It->second;
+ ValueLatticeElement LV = It->second;
if (!isConstant(LV))
return false;
}
/// Helper to return a Constant if \p LV is either a constant or a constant
/// range with a single element.
- Constant *getConstant(const LatticeVal &LV) const {
+ Constant *getConstant(const ValueLatticeElement &LV) const {
if (LV.isConstant())
return LV.getConstant();
}
private:
- ConstantInt *getConstantInt(const LatticeVal &IV) const {
+ ConstantInt *getConstantInt(const ValueLatticeElement &IV) const {
return dyn_cast_or_null<ConstantInt>(getConstant(IV));
}
// pushToWorkList - Helper for markConstant/markOverdefined
- void pushToWorkList(LatticeVal &IV, Value *V) {
+ void pushToWorkList(ValueLatticeElement &IV, Value *V) {
if (IV.isOverdefined())
return OverdefinedInstWorkList.push_back(V);
InstWorkList.push_back(V);
// Helper to push \p V to the worklist, after updating it to \p IV. Also
// prints a debug message with the updated value.
- void pushToWorkListMsg(LatticeVal &IV, Value *V) {
+ void pushToWorkListMsg(ValueLatticeElement &IV, Value *V) {
LLVM_DEBUG(dbgs() << "updated " << IV << ": " << *V << '\n');
if (IV.isOverdefined())
return OverdefinedInstWorkList.push_back(V);
// markConstant - Make a value be marked as "constant". If the value
// is not already a constant, add it to the instruction work list so that
// the users of the instruction are updated later.
- bool markConstant(LatticeVal &IV, Value *V, Constant *C) {
+ bool markConstant(ValueLatticeElement &IV, Value *V, Constant *C) {
if (!IV.markConstant(C)) return false;
LLVM_DEBUG(dbgs() << "markConstant: " << *C << ": " << *V << '\n');
pushToWorkList(IV, V);
// markOverdefined - Make a value be marked as "overdefined". If the
// value is not already overdefined, add it to the overdefined instruction
// work list so that the users of the instruction are updated later.
- bool markOverdefined(LatticeVal &IV, Value *V) {
+ bool markOverdefined(ValueLatticeElement &IV, Value *V) {
if (!IV.markOverdefined()) return false;
LLVM_DEBUG(dbgs() << "markOverdefined: ";
return true;
}
- bool mergeInValue(LatticeVal &IV, Value *V, LatticeVal MergeWithV,
- bool Widen = true) {
+ bool mergeInValue(ValueLatticeElement &IV, Value *V,
+ ValueLatticeElement MergeWithV, bool Widen = true) {
// Do a simple form of widening, to avoid extending a range repeatedly in a
// loop. If IV is a constant range, it means we already set it once. If
// MergeWithV would extend IV, mark V as overdefined.
return false;
}
- bool mergeInValue(Value *V, LatticeVal MergeWithV, bool Widen = true) {
+ bool mergeInValue(Value *V, ValueLatticeElement MergeWithV,
+ bool Widen = true) {
assert(!V->getType()->isStructTy() &&
"non-structs should use markConstant");
return mergeInValue(ValueState[V], V, MergeWithV, Widen);
}
- /// getValueState - Return the LatticeVal object that corresponds to the
- /// value. This function handles the case when the value hasn't been seen yet
- /// by properly seeding constants etc.
- LatticeVal &getValueState(Value *V) {
+ /// getValueState - Return the ValueLatticeElement object that corresponds to
+ /// the value. This function handles the case when the value hasn't been seen
+ /// yet by properly seeding constants etc.
+ ValueLatticeElement &getValueState(Value *V) {
assert(!V->getType()->isStructTy() && "Should use getStructValueState");
- std::pair<DenseMap<Value*, LatticeVal>::iterator, bool> I =
- ValueState.insert(std::make_pair(V, LatticeVal()));
- LatticeVal &LV = I.first->second;
+ auto I = ValueState.insert(std::make_pair(V, ValueLatticeElement()));
+ ValueLatticeElement &LV = I.first->second;
if (!I.second)
return LV; // Common case, already in the map.
return LV;
}
- /// getStructValueState - Return the LatticeVal object that corresponds to the
- /// value/field pair. This function handles the case when the value hasn't
- /// been seen yet by properly seeding constants etc.
- LatticeVal &getStructValueState(Value *V, unsigned i) {
+ /// getStructValueState - Return the ValueLatticeElement object that
+ /// corresponds to the value/field pair. This function handles the case when
+ /// the value hasn't been seen yet by properly seeding constants etc.
+ ValueLatticeElement &getStructValueState(Value *V, unsigned i) {
assert(V->getType()->isStructTy() && "Should use getValueState");
assert(i < cast<StructType>(V->getType())->getNumElements() &&
"Invalid element #");
- std::pair<DenseMap<std::pair<Value*, unsigned>, LatticeVal>::iterator,
- bool> I = StructValueState.insert(
- std::make_pair(std::make_pair(V, i), LatticeVal()));
- LatticeVal &LV = I.first->second;
+ auto I = StructValueState.insert(
+ std::make_pair(std::make_pair(V, i), ValueLatticeElement()));
+ ValueLatticeElement &LV = I.first->second;
if (!I.second)
return LV; // Common case, already in the map.
return;
}
- LatticeVal BCValue = getValueState(BI->getCondition());
+ ValueLatticeElement BCValue = getValueState(BI->getCondition());
ConstantInt *CI = getConstantInt(BCValue);
if (!CI) {
// Overdefined condition variables, and branches on unfoldable constant
Succs[0] = true;
return;
}
- LatticeVal SCValue = getValueState(SI->getCondition());
+ ValueLatticeElement SCValue = getValueState(SI->getCondition());
ConstantInt *CI = getConstantInt(SCValue);
if (!CI) { // Overdefined or unknown condition?
// the target as executable.
if (auto *IBR = dyn_cast<IndirectBrInst>(&TI)) {
// Casts are folded by visitCastInst.
- LatticeVal IBRValue = getValueState(IBR->getAddress());
+ ValueLatticeElement IBRValue = getValueState(IBR->getAddress());
BlockAddress *Addr = dyn_cast_or_null<BlockAddress>(getConstant(IBRValue));
if (!Addr) { // Overdefined or unknown condition?
// All destinations are executable!
// If there are no executable operands, the PHI remains unknown.
bool Changed = false;
for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
- LatticeVal IV = getValueState(PN.getIncomingValue(i));
+ ValueLatticeElement IV = getValueState(PN.getIncomingValue(i));
if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent()))
continue;
- LatticeVal &Res = getValueState(&PN);
+ ValueLatticeElement &Res = getValueState(&PN);
Changed |= Res.mergeIn(IV, DL);
if (Res.isOverdefined())
break;
// If we are tracking the return value of this function, merge it in.
if (!TrackedRetVals.empty() && !ResultOp->getType()->isStructTy()) {
- MapVector<Function*, LatticeVal>::iterator TFRVI =
- TrackedRetVals.find(F);
+ auto TFRVI = TrackedRetVals.find(F);
if (TFRVI != TrackedRetVals.end()) {
mergeInValue(TFRVI->second, F, getValueState(ResultOp));
return;
if (isOverdefined(ValueState[&I]))
return (void)markOverdefined(&I);
- LatticeVal OpSt = getValueState(I.getOperand(0));
+ ValueLatticeElement OpSt = getValueState(I.getOperand(0));
if (Constant *OpC = getConstant(OpSt)) {
// Fold the constant as we build.
Constant *C = ConstantFoldCastOperand(I.getOpcode(), OpC, I.getType(), DL);
Value *AggVal = EVI.getAggregateOperand();
if (AggVal->getType()->isStructTy()) {
unsigned i = *EVI.idx_begin();
- LatticeVal EltVal = getStructValueState(AggVal, i);
+ ValueLatticeElement EltVal = getStructValueState(AggVal, i);
mergeInValue(getValueState(&EVI), &EVI, EltVal);
} else {
// Otherwise, must be extracting from an array.
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
// This passes through all values that aren't the inserted element.
if (i != Idx) {
- LatticeVal EltVal = getStructValueState(Aggr, i);
+ ValueLatticeElement EltVal = getStructValueState(Aggr, i);
mergeInValue(getStructValueState(&IVI, i), &IVI, EltVal);
continue;
}
// We don't track structs in structs.
markOverdefined(getStructValueState(&IVI, i), &IVI);
else {
- LatticeVal InVal = getValueState(Val);
+ ValueLatticeElement InVal = getValueState(Val);
mergeInValue(getStructValueState(&IVI, i), &IVI, InVal);
}
}
if (ValueState[&I].isOverdefined())
return (void)markOverdefined(&I);
- LatticeVal CondValue = getValueState(I.getCondition());
+ ValueLatticeElement CondValue = getValueState(I.getCondition());
if (CondValue.isUnknownOrUndef())
return;
// Otherwise, the condition is overdefined or a constant we can't evaluate.
// See if we can produce something better than overdefined based on the T/F
// value.
- LatticeVal TVal = getValueState(I.getTrueValue());
- LatticeVal FVal = getValueState(I.getFalseValue());
+ ValueLatticeElement TVal = getValueState(I.getTrueValue());
+ ValueLatticeElement FVal = getValueState(I.getFalseValue());
bool Changed = ValueState[&I].mergeIn(TVal, DL);
Changed |= ValueState[&I].mergeIn(FVal, DL);
// Handle Unary Operators.
void SCCPSolver::visitUnaryOperator(Instruction &I) {
- LatticeVal V0State = getValueState(I.getOperand(0));
+ ValueLatticeElement V0State = getValueState(I.getOperand(0));
- LatticeVal &IV = ValueState[&I];
+ ValueLatticeElement &IV = ValueState[&I];
// ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would
// discover a concrete value later.
if (isOverdefined(IV))
// Handle Binary Operators.
void SCCPSolver::visitBinaryOperator(Instruction &I) {
- LatticeVal V1State = getValueState(I.getOperand(0));
- LatticeVal V2State = getValueState(I.getOperand(1));
+ ValueLatticeElement V1State = getValueState(I.getOperand(0));
+ ValueLatticeElement V2State = getValueState(I.getOperand(1));
- LatticeVal &IV = ValueState[&I];
+ ValueLatticeElement &IV = ValueState[&I];
if (IV.isOverdefined())
return;
B = V2State.getConstantRange();
ConstantRange R = A.binaryOp(cast<BinaryOperator>(&I)->getOpcode(), B);
- mergeInValue(&I, LatticeVal::getRange(R));
+ mergeInValue(&I, ValueLatticeElement::getRange(R));
// TODO: Currently we do not exploit special values that produce something
// better than overdefined with an overdefined operand for vector or floating
if (C) {
if (isa<UndefValue>(C))
return;
- LatticeVal CV;
+ ValueLatticeElement CV;
CV.markConstant(C);
mergeInValue(&I, CV);
return;
Operands.reserve(I.getNumOperands());
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
- LatticeVal State = getValueState(I.getOperand(i));
+ ValueLatticeElement State = getValueState(I.getOperand(i));
if (State.isUnknownOrUndef())
return; // Operands are not resolved yet.
return (void)markOverdefined(&SI);
GlobalVariable *GV = cast<GlobalVariable>(SI.getOperand(1));
- DenseMap<GlobalVariable*, LatticeVal>::iterator I = TrackedGlobals.find(GV);
+ auto I = TrackedGlobals.find(GV);
if (I == TrackedGlobals.end())
return;
if (isOverdefined(ValueState[&I]))
return (void)markOverdefined(&I);
- LatticeVal PtrVal = getValueState(I.getOperand(0));
+ ValueLatticeElement PtrVal = getValueState(I.getOperand(0));
if (PtrVal.isUnknownOrUndef())
return; // The pointer is not resolved yet!
- LatticeVal &IV = ValueState[&I];
+ ValueLatticeElement &IV = ValueState[&I];
if (!isConstant(PtrVal) || I.isVolatile())
return (void)markOverdefined(IV, &I);
if (auto *GV = dyn_cast<GlobalVariable>(Ptr)) {
if (!TrackedGlobals.empty()) {
// If we are tracking this global, merge in the known value for it.
- DenseMap<GlobalVariable*, LatticeVal>::iterator It =
- TrackedGlobals.find(GV);
+ auto It = TrackedGlobals.find(GV);
if (It != TrackedGlobals.end()) {
mergeInValue(IV, &I, It->second);
return;
++AI) {
if (AI->get()->getType()->isStructTy())
return markOverdefined(I); // Can't handle struct args.
- LatticeVal State = getValueState(*AI);
+ ValueLatticeElement State = getValueState(*AI);
if (State.isUnknownOrUndef())
return; // Operands are not resolved yet.
if (auto *STy = dyn_cast<StructType>(AI->getType())) {
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- LatticeVal CallArg = getStructValueState(*CAI, i);
+ ValueLatticeElement CallArg = getStructValueState(*CAI, i);
mergeInValue(getStructValueState(&*AI, i), &*AI, CallArg);
}
} else
if (CmpOp0 != CopyOf)
std::swap(CmpOp0, CmpOp1);
- LatticeVal OriginalVal = getValueState(CopyOf);
- LatticeVal EqVal = getValueState(CmpOp1);
- LatticeVal &IV = ValueState[I];
+ ValueLatticeElement OriginalVal = getValueState(CopyOf);
+ ValueLatticeElement EqVal = getValueState(CmpOp1);
+ ValueLatticeElement &IV = ValueState[I];
if (PBranch->TrueEdge && Cmp->getPredicate() == CmpInst::ICMP_EQ) {
addAdditionalUser(CmpOp1, I);
if (isConstant(OriginalVal))
mergeInValue(getStructValueState(I, i), I,
TrackedMultipleRetVals[std::make_pair(F, i)]);
} else {
- MapVector<Function*, LatticeVal>::iterator TFRVI = TrackedRetVals.find(F);
+ auto TFRVI = TrackedRetVals.find(F);
if (TFRVI == TrackedRetVals.end())
return handleCallOverdefined(CS); // Not tracking this callee.
// Send the results of everything else to overdefined. We could be
// more precise than this but it isn't worth bothering.
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- LatticeVal &LV = getStructValueState(&I, i);
+ ValueLatticeElement &LV = getStructValueState(&I, i);
if (LV.isUnknownOrUndef())
markOverdefined(LV, &I);
}
continue;
}
- LatticeVal &LV = getValueState(&I);
+ ValueLatticeElement &LV = getValueState(&I);
if (!LV.isUnknownOrUndef())
continue;
static bool tryToReplaceWithConstant(SCCPSolver &Solver, Value *V) {
Constant *Const = nullptr;
if (V->getType()->isStructTy()) {
- std::vector<LatticeVal> IVs = Solver.getStructLatticeValueFor(V);
- if (any_of(IVs, [](const LatticeVal &LV) { return isOverdefined(LV); }))
+ std::vector<ValueLatticeElement> IVs = Solver.getStructLatticeValueFor(V);
+ if (any_of(IVs,
+ [](const ValueLatticeElement &LV) { return isOverdefined(LV); }))
return false;
std::vector<Constant *> ConstVals;
auto *ST = cast<StructType>(V->getType());
for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {
- LatticeVal V = IVs[i];
+ ValueLatticeElement V = IVs[i];
ConstVals.push_back(isConstant(V)
? Solver.getConstant(V)
: UndefValue::get(ST->getElementType(i)));
}
Const = ConstantStruct::get(ST, ConstVals);
} else {
- const LatticeVal &IV = Solver.getLatticeValueFor(V);
+ const ValueLatticeElement &IV = Solver.getLatticeValueFor(V);
if (isOverdefined(IV))
return false;
if (!CallSite(U))
return true;
if (U->getType()->isStructTy()) {
- return all_of(
- Solver.getStructLatticeValueFor(U),
- [](const LatticeVal &LV) { return !isOverdefined(LV); });
+ return all_of(Solver.getStructLatticeValueFor(U),
+ [](const ValueLatticeElement &LV) {
+ return !isOverdefined(LV);
+ });
}
return !isOverdefined(Solver.getLatticeValueFor(U));
}) &&
// whether other functions are optimizable.
SmallVector<ReturnInst*, 8> ReturnsToZap;
- const MapVector<Function*, LatticeVal> &RV = Solver.getTrackedRetVals();
- for (const auto &I : RV) {
+ for (const auto &I : Solver.getTrackedRetVals()) {
Function *F = I.first;
if (isOverdefined(I.second) || F->getReturnType()->isVoidTy())
continue;
// If we inferred constant or undef values for globals variables, we can
// delete the global and any stores that remain to it.
- const DenseMap<GlobalVariable*, LatticeVal> &TG = Solver.getTrackedGlobals();
- for (DenseMap<GlobalVariable*, LatticeVal>::const_iterator I = TG.begin(),
- E = TG.end(); I != E; ++I) {
- GlobalVariable *GV = I->first;
- if (isOverdefined(I->second))
+ for (auto &I : make_early_inc_range(Solver.getTrackedGlobals())) {
+ GlobalVariable *GV = I.first;
+ if (isOverdefined(I.second))
continue;
LLVM_DEBUG(dbgs() << "Found that GV '" << GV->getName()
<< "' is constant!\n");