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;
111template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
130 using Edge = std::pair<BasicBlock *, BasicBlock *>;
134 std::set<Edge> KnownFeasibleEdges;
139 : LatticeFunc(Lattice) {}
152 auto I = ValueState.find(
Key);
153 return I != ValueState.end() ?
I->second : LatticeFunc->getUntrackedVal();
167 bool AggressiveUndef =
false);
173 return BBExecutable.count(BB);
184 void UpdateState(LatticeKey
Key, LatticeVal LV);
193 bool AggressiveUndef);
204template <
class LatticeKey,
class LatticeVal>
209 else if (V == OverdefinedVal)
211 else if (V == UntrackedVal)
214 OS <<
"unknown lattice value";
217template <
class LatticeKey,
class LatticeVal>
220 OS <<
"unknown lattice key";
227template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
230 auto I = ValueState.find(
Key);
231 if (
I != ValueState.end())
234 if (LatticeFunc->IsUntrackedValue(
Key))
235 return LatticeFunc->getUntrackedVal();
236 LatticeVal LV = LatticeFunc->ComputeLatticeVal(
Key);
239 if (LV == LatticeFunc->getUntrackedVal())
241 return ValueState[
Key] = std::move(LV);
244template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
245void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::UpdateState(LatticeKey
Key,
247 auto [
I, Inserted] = ValueState.try_emplace(
Key);
248 if (!Inserted &&
I->second == LV)
253 I->second = std::move(LV);
254 if (
Value *V = KeyInfo::getValueFromLatticeKey(
Key))
255 ValueWorkList.push_back(V);
258template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
261 if (!BBExecutable.insert(BB).second)
264 BBWorkList.push_back(BB);
267template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
268void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::markEdgeExecutable(
270 if (!KnownFeasibleEdges.insert(Edge(Source, Dest)).second)
273 LLVM_DEBUG(
dbgs() <<
"Marking Edge Executable: " << Source->getName()
274 <<
" -> " << Dest->
getName() <<
"\n");
276 if (BBExecutable.count(Dest)) {
283 MarkBlockExecutable(Dest);
287template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
288void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getFeasibleSuccessors(
290 Succs.resize(TI.getNumSuccessors());
291 if (TI.getNumSuccessors() == 0)
295 if (BI->isUnconditional()) {
303 getValueState(KeyInfo::getLatticeKeyFromValue(BI->getCondition()));
305 BCValue = getExistingValueState(
306 KeyInfo::getLatticeKeyFromValue(BI->getCondition()));
308 if (BCValue == LatticeFunc->getOverdefinedVal() ||
309 BCValue == LatticeFunc->getUntrackedVal()) {
311 Succs[0] = Succs[1] =
true;
316 if (BCValue == LatticeFunc->getUndefVal())
321 std::move(BCValue), BI->getCondition()->getType()));
324 Succs[0] = Succs[1] =
true;
329 Succs[
C->isNullValue()] =
true;
335 Succs.assign(Succs.size(),
true);
342 SCValue = getValueState(KeyInfo::getLatticeKeyFromValue(
SI.getCondition()));
344 SCValue = getExistingValueState(
345 KeyInfo::getLatticeKeyFromValue(
SI.getCondition()));
347 if (SCValue == LatticeFunc->getOverdefinedVal() ||
348 SCValue == LatticeFunc->getUntrackedVal()) {
350 Succs.assign(TI.getNumSuccessors(),
true);
355 if (SCValue == LatticeFunc->getUndefVal())
359 std::move(SCValue),
SI.getCondition()->getType()));
362 Succs.assign(TI.getNumSuccessors(),
true);
366 Succs[Case.getSuccessorIndex()] =
true;
369template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
374 getFeasibleSuccessors(*TI, SuccFeasible, AggressiveUndef);
383template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
384void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitTerminator(
387 getFeasibleSuccessors(TI, SuccFeasible,
true);
392 for (
unsigned i = 0, e = SuccFeasible.
size(); i != e; ++i)
397template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
398void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitPHINode(PHINode &PN) {
402 if (LatticeFunc->IsSpecialCasedPHI(&PN)) {
403 SmallDenseMap<LatticeKey, LatticeVal, 16> ChangedValues;
404 LatticeFunc->ComputeInstructionState(PN, ChangedValues, *
this);
405 for (
auto &ChangedValue : ChangedValues)
406 if (ChangedValue.second != LatticeFunc->getUntrackedVal())
407 UpdateState(std::move(ChangedValue.first),
408 std::move(ChangedValue.second));
412 LatticeKey
Key = KeyInfo::getLatticeKeyFromValue(&PN);
413 LatticeVal PNIV = getValueState(
Key);
414 LatticeVal Overdefined = LatticeFunc->getOverdefinedVal();
417 if (PNIV == Overdefined || PNIV == LatticeFunc->getUntrackedVal())
422 if (PN.getNumIncomingValues() > 64) {
423 UpdateState(
Key, Overdefined);
430 for (
unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
432 if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent(),
true))
437 getValueState(KeyInfo::getLatticeKeyFromValue(PN.getIncomingValue(i)));
439 PNIV = LatticeFunc->MergeValues(PNIV, OpVal);
441 if (PNIV == Overdefined)
446 UpdateState(
Key, PNIV);
449template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
450void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitInst(
Instruction &
I) {
454 return visitPHINode(*PN);
459 LatticeFunc->ComputeInstructionState(
I, ChangedValues, *
this);
460 for (
auto &ChangedValue : ChangedValues)
461 if (ChangedValue.second != LatticeFunc->getUntrackedVal())
462 UpdateState(ChangedValue.first, ChangedValue.second);
464 if (
I.isTerminator())
468template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
471 while (!BBWorkList.empty() || !ValueWorkList.empty()) {
473 while (!ValueWorkList.empty()) {
474 Value *V = ValueWorkList.pop_back_val();
482 if (BBExecutable.count(Inst->getParent()))
487 while (!BBWorkList.empty()) {
500template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
503 if (ValueState.empty())
509 OS <<
"ValueState:\n";
510 for (
auto &Entry : ValueState) {
511 std::tie(
Key, LV) = Entry;
512 if (LV == LatticeFunc->getUntrackedVal())
515 LatticeFunc->PrintLatticeVal(LV, OS);
517 LatticeFunc->PrintLatticeKey(
Key, OS);
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the SmallPtrSet class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton 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, SmallDenseMap< LatticeKey, LatticeVal, 16 > &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...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Conditional or Unconditional Branch instruction.
This is an important base class in LLVM.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
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.
iterator_range< user_iterator > users()
LLVM_ABI 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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
A template for translating between LLVM Values and LatticeKeys.