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);
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>
247 auto I = ValueState.find(Key);
248 if (
I != ValueState.end() &&
I->second == LV)
253 ValueState[Key] = 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>
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)) {
281 visitPHINode(*cast<PHINode>(
I));
283 MarkBlockExecutable(Dest);
287template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
288void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getFeasibleSuccessors(
289 Instruction &TI, SmallVectorImpl<bool> &Succs,
bool AggressiveUndef) {
290 Succs.resize(TI.getNumSuccessors());
291 if (TI.getNumSuccessors() == 0)
294 if (BranchInst *BI = dyn_cast<BranchInst>(&TI)) {
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())
320 dyn_cast_or_null<Constant>(LatticeFunc->GetValueFromLatticeVal(
321 std::move(BCValue), BI->getCondition()->getType()));
322 if (!
C || !isa<ConstantInt>(
C)) {
324 Succs[0] = Succs[1] =
true;
329 Succs[
C->isNullValue()] =
true;
333 if (!isa<SwitchInst>(TI)) {
335 Succs.assign(Succs.size(),
true);
339 SwitchInst &
SI = cast<SwitchInst>(TI);
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())
358 Constant *
C = dyn_cast_or_null<Constant>(LatticeFunc->GetValueFromLatticeVal(
359 std::move(SCValue),
SI.getCondition()->getType()));
360 if (!
C || !isa<ConstantInt>(
C)) {
362 Succs.assign(TI.getNumSuccessors(),
true);
365 SwitchInst::CaseHandle Case = *
SI.findCaseValue(cast<ConstantInt>(
C));
366 Succs[Case.getSuccessorIndex()] =
true;
369template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
374 getFeasibleSuccessors(*TI, SuccFeasible, AggressiveUndef);
383template <
class LatticeKey,
class LatticeVal,
class KeyInfo>
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) {
453 if (PHINode *PN = dyn_cast<PHINode>(&
I))
454 return visitPHINode(*PN);
458 SmallDenseMap<LatticeKey, LatticeVal, 16> ChangedValues;
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();
480 for (
User *U : V->users())
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);
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, 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...
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.