14#ifndef LLVM_ANALYSIS_SPARSEPROPAGATION_H
15#define LLVM_ANALYSIS_SPARSEPROPAGATION_H
23#define DEBUG_TYPE "sparseprop"
34template <
class LatticeKey,
class LatticeVal,
49 LatticeVal UndefVal, OverdefinedVal, UntrackedVal;
53 LatticeVal untrackedVal) {
55 OverdefinedVal = overdefinedVal;
56 UntrackedVal = untrackedVal;
112template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
131 using Edge = std::pair<BasicBlock *, BasicBlock *>;
135 std::set<Edge> KnownFeasibleEdges;
140 : LatticeFunc(Lattice) {}
153 auto I = ValueState.
find(Key);
168 bool AggressiveUndef =
false);
174 return BBExecutable.
count(BB);
185 void UpdateState(LatticeKey Key, LatticeVal LV);
194 bool AggressiveUndef);
205template <
class LatticeKey,
class LatticeVal>
210 else if (V == OverdefinedVal)
212 else if (V == UntrackedVal)
215 OS <<
"unknown lattice value";
218template <
class LatticeKey,
class LatticeVal>
221 OS <<
"unknown lattice key";
228template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
231 auto I = ValueState.find(Key);
232 if (
I != ValueState.end())
235 if (LatticeFunc->IsUntrackedValue(Key))
236 return LatticeFunc->getUntrackedVal();
237 LatticeVal LV = LatticeFunc->ComputeLatticeVal(Key);
240 if (LV == LatticeFunc->getUntrackedVal())
242 return ValueState[Key] = std::move(LV);
245template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
248 auto I = ValueState.find(Key);
249 if (
I != ValueState.end() &&
I->second == LV)
254 ValueState[Key] = std::move(LV);
255 if (
Value *V = KeyInfo::getValueFromLatticeKey(Key))
256 ValueWorkList.push_back(V);
259template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
262 if (!BBExecutable.insert(BB).second)
265 BBWorkList.push_back(BB);
268template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
271 if (!KnownFeasibleEdges.insert(Edge(Source, Dest)).second)
274 LLVM_DEBUG(
dbgs() <<
"Marking Edge Executable: " << Source->getName()
275 <<
" -> " << Dest->
getName() <<
"\n");
277 if (BBExecutable.count(Dest)) {
282 visitPHINode(*cast<PHINode>(
I));
284 MarkBlockExecutable(Dest);
288template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
289void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getFeasibleSuccessors(
290 Instruction &TI, SmallVectorImpl<bool> &Succs,
bool AggressiveUndef) {
291 Succs.resize(TI.getNumSuccessors());
292 if (TI.getNumSuccessors() == 0)
295 if (BranchInst *BI = dyn_cast<BranchInst>(&TI)) {
296 if (BI->isUnconditional()) {
304 getValueState(KeyInfo::getLatticeKeyFromValue(BI->getCondition()));
306 BCValue = getExistingValueState(
307 KeyInfo::getLatticeKeyFromValue(BI->getCondition()));
309 if (BCValue == LatticeFunc->getOverdefinedVal() ||
310 BCValue == LatticeFunc->getUntrackedVal()) {
312 Succs[0] = Succs[1] =
true;
317 if (BCValue == LatticeFunc->getUndefVal())
321 dyn_cast_or_null<Constant>(LatticeFunc->GetValueFromLatticeVal(
322 std::move(BCValue), BI->getCondition()->getType()));
323 if (!
C || !isa<ConstantInt>(
C)) {
325 Succs[0] = Succs[1] =
true;
330 Succs[
C->isNullValue()] =
true;
334 if (!isa<SwitchInst>(TI)) {
336 Succs.assign(Succs.size(),
true);
340 SwitchInst &
SI = cast<SwitchInst>(TI);
343 SCValue = getValueState(KeyInfo::getLatticeKeyFromValue(
SI.getCondition()));
345 SCValue = getExistingValueState(
346 KeyInfo::getLatticeKeyFromValue(
SI.getCondition()));
348 if (SCValue == LatticeFunc->getOverdefinedVal() ||
349 SCValue == LatticeFunc->getUntrackedVal()) {
351 Succs.assign(TI.getNumSuccessors(),
true);
356 if (SCValue == LatticeFunc->getUndefVal())
359 Constant *
C = dyn_cast_or_null<Constant>(LatticeFunc->GetValueFromLatticeVal(
360 std::move(SCValue),
SI.getCondition()->getType()));
361 if (!
C || !isa<ConstantInt>(
C)) {
363 Succs.assign(TI.getNumSuccessors(),
true);
366 SwitchInst::CaseHandle Case = *
SI.findCaseValue(cast<ConstantInt>(
C));
367 Succs[Case.getSuccessorIndex()] =
true;
370template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
375 getFeasibleSuccessors(*TI, SuccFeasible, AggressiveUndef);
384template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
388 getFeasibleSuccessors(TI, SuccFeasible,
true);
393 for (
unsigned i = 0, e = SuccFeasible.
size(); i != e; ++i)
398template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
399void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitPHINode(PHINode &PN) {
403 if (LatticeFunc->IsSpecialCasedPHI(&PN)) {
404 DenseMap<LatticeKey, LatticeVal> ChangedValues;
405 LatticeFunc->ComputeInstructionState(PN, ChangedValues, *
this);
406 for (
auto &ChangedValue : ChangedValues)
407 if (ChangedValue.second != LatticeFunc->getUntrackedVal())
408 UpdateState(std::move(ChangedValue.first),
409 std::move(ChangedValue.second));
413 LatticeKey
Key = KeyInfo::getLatticeKeyFromValue(&PN);
414 LatticeVal PNIV = getValueState(Key);
415 LatticeVal Overdefined = LatticeFunc->getOverdefinedVal();
418 if (PNIV == Overdefined || PNIV == LatticeFunc->getUntrackedVal())
423 if (PN.getNumIncomingValues() > 64) {
424 UpdateState(Key, Overdefined);
431 for (
unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
433 if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent(),
true))
438 getValueState(KeyInfo::getLatticeKeyFromValue(PN.getIncomingValue(i)));
440 PNIV = LatticeFunc->MergeValues(PNIV, OpVal);
442 if (PNIV == Overdefined)
447 UpdateState(Key, PNIV);
450template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
451void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitInst(Instruction &
I) {
454 if (PHINode *PN = dyn_cast<PHINode>(&
I))
455 return visitPHINode(*PN);
459 DenseMap<LatticeKey, LatticeVal> ChangedValues;
460 LatticeFunc->ComputeInstructionState(
I, ChangedValues, *
this);
461 for (
auto &ChangedValue : ChangedValues)
462 if (ChangedValue.second != LatticeFunc->getUntrackedVal())
463 UpdateState(ChangedValue.first, ChangedValue.second);
465 if (
I.isTerminator())
469template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
472 while (!BBWorkList.empty() || !ValueWorkList.empty()) {
474 while (!ValueWorkList.empty()) {
475 Value *V = ValueWorkList.pop_back_val();
481 for (
User *U : V->users())
483 if (BBExecutable.count(Inst->getParent()))
488 while (!BBWorkList.empty()) {
501template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
504 if (ValueState.empty())
510 OS <<
"ValueState:\n";
511 for (
auto &Entry : ValueState) {
512 std::tie(Key, LV) = Entry;
513 if (LV == LatticeFunc->getUntrackedVal())
516 LatticeFunc->PrintLatticeVal(LV,
OS);
518 LatticeFunc->PrintLatticeKey(Key,
OS);
BlockVerifier::State From
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
This file defines the SmallPtrSet class.
AbstractLatticeFunction - This class is implemented by the dataflow instance to specify what the latt...
LatticeVal getOverdefinedVal() const
AbstractLatticeFunction(LatticeVal undefVal, LatticeVal overdefinedVal, LatticeVal untrackedVal)
virtual void ComputeInstructionState(Instruction &I, DenseMap< LatticeKey, LatticeVal > &ChangedValues, SparseSolver< LatticeKey, LatticeVal > &SS)=0
ComputeInstructionState - Compute the LatticeKeys that change as a result of executing instruction I.
virtual void PrintLatticeKey(LatticeKey Key, raw_ostream &OS)
PrintLatticeKey - Render the given LatticeKey to the specified stream.
virtual Value * GetValueFromLatticeVal(LatticeVal LV, Type *Ty=nullptr)
GetValueFromLatticeVal - If the given LatticeVal is representable as an LLVM value,...
virtual bool IsUntrackedValue(LatticeKey Key)
IsUntrackedValue - If the specified LatticeKey is obviously uninteresting to the analysis (i....
virtual void PrintLatticeVal(LatticeVal LV, raw_ostream &OS)
PrintLatticeVal - Render the given LatticeVal to the specified stream.
LatticeVal getUntrackedVal() const
virtual LatticeVal MergeValues(LatticeVal X, LatticeVal Y)
MergeValues - Compute and return the merge of the two specified lattice values.
virtual LatticeVal ComputeLatticeVal(LatticeKey Key)
ComputeLatticeVal - Compute and return a LatticeVal corresponding to the given LatticeKey.
virtual ~AbstractLatticeFunction()=default
LatticeVal getUndefVal() const
virtual bool IsSpecialCasedPHI(PHINode *PN)
IsSpecialCasedPHI - Given a PHI node, determine whether this PHI node is one that the we want to hand...
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
InstListType::iterator iterator
Instruction iterators...
iterator find(const_arg_type_t< KeyT > Val)
unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
SparseSolver - This class is a general purpose solver for Sparse Conditional Propagation with a progr...
bool isEdgeFeasible(BasicBlock *From, BasicBlock *To, bool AggressiveUndef=false)
isEdgeFeasible - Return true if the control flow edge from the 'From' basic block to the 'To' basic b...
void Print(raw_ostream &OS) const
LatticeVal getValueState(LatticeKey Key)
getValueState - Return the LatticeVal object corresponding to the given value from the ValueState map...
SparseSolver(AbstractLatticeFunction< LatticeKey, LatticeVal > *Lattice)
SparseSolver(const SparseSolver &)=delete
void MarkBlockExecutable(BasicBlock *BB)
MarkBlockExecutable - This method can be used by clients to mark all of the blocks that are known to ...
void Solve()
Solve - Solve for constants and executable blocks.
LatticeVal getExistingValueState(LatticeKey Key) const
getExistingValueState - Return the LatticeVal object corresponding to the given value from the ValueS...
bool isBlockExecutable(BasicBlock *BB) const
isBlockExecutable - Return true if there are any known feasible edges into the basic block.
SparseSolver & operator=(const SparseSolver &)=delete
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
StringRef getName() const
Return a constant reference to the value's name.
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
A template for translating between LLVM Values and LatticeKeys.