[llvm] r314734 - Template the sparse propagation solver instead of using void pointers
Daniel Berlin via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 2 15:49:49 PDT 2017
Author: dannyb
Date: Mon Oct 2 15:49:49 2017
New Revision: 314734
URL: http://llvm.org/viewvc/llvm-project?rev=314734&view=rev
Log:
Template the sparse propagation solver instead of using void pointers
Summary:
This avoids using void * as the type of the lattice value and ugly casts needed to make that happen.
(If folks want to use references, etc, they can use a reference_wrapper).
Reviewers: davide, mssimpso
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D38476
Modified:
llvm/trunk/include/llvm/Analysis/SparsePropagation.h
llvm/trunk/lib/Analysis/SparsePropagation.cpp
Modified: llvm/trunk/include/llvm/Analysis/SparsePropagation.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/SparsePropagation.h?rev=314734&r1=314733&r2=314734&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/SparsePropagation.h (original)
+++ llvm/trunk/include/llvm/Analysis/SparsePropagation.h Mon Oct 2 15:49:49 2017
@@ -30,22 +30,19 @@ class Function;
class Instruction;
class PHINode;
class raw_ostream;
-class SparseSolver;
+template <class LatticeVal> class SparseSolver;
class TerminatorInst;
class Value;
template <typename T> class SmallVectorImpl;
/// AbstractLatticeFunction - This class is implemented by the dataflow instance
-/// to specify what the lattice values are and how they handle merges etc.
-/// This gives the client the power to compute lattice values from instructions,
-/// constants, etc. The requirement is that lattice values must all fit into
-/// a void*. If a void* is not sufficient, the implementation should use this
-/// pointer to be a pointer into a uniquing set or something.
-///
-class AbstractLatticeFunction {
-public:
- using LatticeVal = void *;
+/// to specify what the lattice values are and how they handle merges etc. This
+/// gives the client the power to compute lattice values from instructions,
+/// constants, etc. The current requirement is that lattice values must be
+/// copyable. At the moment, nothing tries to avoid copying.
+
+template <class LatticeVal> class AbstractLatticeFunction {
private:
LatticeVal UndefVal, OverdefinedVal, UntrackedVal;
@@ -81,7 +78,8 @@ public:
/// GetConstant - If the specified lattice value is representable as an LLVM
/// constant value, return it. Otherwise return null. The returned value
/// must be in the same LLVM type as Val.
- virtual Constant *GetConstant(LatticeVal LV, Value *Val, SparseSolver &SS) {
+ virtual Constant *GetConstant(LatticeVal LV, Value *Val,
+ SparseSolver<LatticeVal> &SS) {
return nullptr;
}
@@ -100,7 +98,8 @@ public:
/// ComputeInstructionState - Given an instruction and a vector of its operand
/// values, compute the result value of the instruction.
- virtual LatticeVal ComputeInstructionState(Instruction &I, SparseSolver &SS) {
+ virtual LatticeVal ComputeInstructionState(Instruction &I,
+ SparseSolver<LatticeVal> &SS) {
return getOverdefinedVal(); // always safe, never useful.
}
@@ -110,12 +109,11 @@ public:
/// SparseSolver - This class is a general purpose solver for Sparse Conditional
/// Propagation with a programmable lattice function.
-class SparseSolver {
- using LatticeVal = AbstractLatticeFunction::LatticeVal;
+template <class LatticeVal> class SparseSolver {
/// LatticeFunc - This is the object that knows the lattice and how to do
/// compute transfer functions.
- AbstractLatticeFunction *LatticeFunc;
+ AbstractLatticeFunction<LatticeVal> *LatticeFunc;
DenseMap<Value *, LatticeVal> ValueState; // The state each value is in.
SmallPtrSet<BasicBlock *, 16> BBExecutable; // The bbs that are executable.
@@ -130,7 +128,7 @@ class SparseSolver {
std::set<Edge> KnownFeasibleEdges;
public:
- explicit SparseSolver(AbstractLatticeFunction *Lattice)
+ explicit SparseSolver(AbstractLatticeFunction<LatticeVal> *Lattice)
: LatticeFunc(Lattice) {}
SparseSolver(const SparseSolver &) = delete;
SparseSolver &operator=(const SparseSolver &) = delete;
@@ -145,7 +143,7 @@ public:
/// value. If an value is not in the map, it is returned as untracked,
/// unlike the getOrInitValueState method.
LatticeVal getLatticeState(Value *V) const {
- DenseMap<Value*, LatticeVal>::const_iterator I = ValueState.find(V);
+ auto I = ValueState.find(V);
return I != ValueState.end() ? I->second : LatticeFunc->getUntrackedVal();
}
Modified: llvm/trunk/lib/Analysis/SparsePropagation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/SparsePropagation.cpp?rev=314734&r1=314733&r2=314734&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/SparsePropagation.cpp (original)
+++ llvm/trunk/lib/Analysis/SparsePropagation.cpp Mon Oct 2 15:49:49 2017
@@ -36,10 +36,13 @@ using namespace llvm;
// AbstractLatticeFunction Implementation
//===----------------------------------------------------------------------===//
-AbstractLatticeFunction::~AbstractLatticeFunction() = default;
+template <class LatticeVal>
+AbstractLatticeFunction<LatticeVal>::~AbstractLatticeFunction() = default;
/// PrintValue - Render the specified lattice value to the specified stream.
-void AbstractLatticeFunction::PrintValue(LatticeVal V, raw_ostream &OS) {
+template <class LatticeVal>
+void AbstractLatticeFunction<LatticeVal>::PrintValue(LatticeVal V,
+ raw_ostream &OS) {
if (V == UndefVal)
OS << "undefined";
else if (V == OverdefinedVal)
@@ -59,8 +62,9 @@ void AbstractLatticeFunction::PrintValue
/// map yet. This function is necessary because not all values should start
/// out in the underdefined state... Arguments should be overdefined, and
/// constants should be marked as constants.
-SparseSolver::LatticeVal SparseSolver::getOrInitValueState(Value *V) {
- DenseMap<Value*, LatticeVal>::iterator I = ValueState.find(V);
+template <class LatticeVal>
+LatticeVal SparseSolver<LatticeVal>::getOrInitValueState(Value *V) {
+ auto I = ValueState.find(V);
if (I != ValueState.end()) return I->second; // Common case, in the map
LatticeVal LV;
@@ -85,8 +89,9 @@ SparseSolver::LatticeVal SparseSolver::g
/// UpdateState - When the state for some instruction is potentially updated,
/// this function notices and adds I to the worklist if needed.
-void SparseSolver::UpdateState(Instruction &Inst, LatticeVal V) {
- DenseMap<Value*, LatticeVal>::iterator I = ValueState.find(&Inst);
+template <class LatticeVal>
+void SparseSolver<LatticeVal>::UpdateState(Instruction &Inst, LatticeVal V) {
+ auto I = ValueState.find(&Inst);
if (I != ValueState.end() && I->second == V)
return; // No change.
@@ -97,7 +102,8 @@ void SparseSolver::UpdateState(Instructi
/// MarkBlockExecutable - This method can be used by clients to mark all of
/// the blocks that are known to be intrinsically live in the processed unit.
-void SparseSolver::MarkBlockExecutable(BasicBlock *BB) {
+template <class LatticeVal>
+void SparseSolver<LatticeVal>::MarkBlockExecutable(BasicBlock *BB) {
DEBUG(dbgs() << "Marking Block Executable: " << BB->getName() << "\n");
BBExecutable.insert(BB); // Basic block is executable!
BBWorkList.push_back(BB); // Add the block to the work list!
@@ -105,7 +111,9 @@ void SparseSolver::MarkBlockExecutable(B
/// markEdgeExecutable - Mark a basic block as executable, adding it to the BB
/// work list if it is not already executable...
-void SparseSolver::markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest) {
+template <class LatticeVal>
+void SparseSolver<LatticeVal>::markEdgeExecutable(BasicBlock *Source,
+ BasicBlock *Dest) {
if (!KnownFeasibleEdges.insert(Edge(Source, Dest)).second)
return; // This edge is already known to be executable!
@@ -125,9 +133,9 @@ void SparseSolver::markEdgeExecutable(Ba
/// getFeasibleSuccessors - Return a vector of booleans to indicate which
/// successors are reachable from a given terminator instruction.
-void SparseSolver::getFeasibleSuccessors(TerminatorInst &TI,
- SmallVectorImpl<bool> &Succs,
- bool AggressiveUndef) {
+template <class LatticeVal>
+void SparseSolver<LatticeVal>::getFeasibleSuccessors(
+ TerminatorInst &TI, SmallVectorImpl<bool> &Succs, bool AggressiveUndef) {
Succs.resize(TI.getNumSuccessors());
if (TI.getNumSuccessors() == 0) return;
@@ -208,8 +216,9 @@ void SparseSolver::getFeasibleSuccessors
/// isEdgeFeasible - Return true if the control flow edge from the 'From'
/// basic block to the 'To' basic block is currently feasible...
-bool SparseSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To,
- bool AggressiveUndef) {
+template <class LatticeVal>
+bool SparseSolver<LatticeVal>::isEdgeFeasible(BasicBlock *From, BasicBlock *To,
+ bool AggressiveUndef) {
SmallVector<bool, 16> SuccFeasible;
TerminatorInst *TI = From->getTerminator();
getFeasibleSuccessors(*TI, SuccFeasible, AggressiveUndef);
@@ -221,7 +230,8 @@ bool SparseSolver::isEdgeFeasible(BasicB
return false;
}
-void SparseSolver::visitTerminatorInst(TerminatorInst &TI) {
+template <class LatticeVal>
+void SparseSolver<LatticeVal>::visitTerminatorInst(TerminatorInst &TI) {
SmallVector<bool, 16> SuccFeasible;
getFeasibleSuccessors(TI, SuccFeasible, true);
@@ -233,7 +243,8 @@ void SparseSolver::visitTerminatorInst(T
markEdgeExecutable(BB, TI.getSuccessor(i));
}
-void SparseSolver::visitPHINode(PHINode &PN) {
+template <class LatticeVal>
+void SparseSolver<LatticeVal>::visitPHINode(PHINode &PN) {
// The lattice function may store more information on a PHINode than could be
// computed from its incoming values. For example, SSI form stores its sigma
// functions as PHINodes with a single incoming value.
@@ -279,7 +290,8 @@ void SparseSolver::visitPHINode(PHINode
UpdateState(PN, PNIV);
}
-void SparseSolver::visitInst(Instruction &I) {
+template <class LatticeVal>
+void SparseSolver<LatticeVal>::visitInst(Instruction &I) {
// PHIs are handled by the propagation logic, they are never passed into the
// transfer functions.
if (PHINode *PN = dyn_cast<PHINode>(&I))
@@ -295,7 +307,7 @@ void SparseSolver::visitInst(Instruction
visitTerminatorInst(*TI);
}
-void SparseSolver::Solve(Function &F) {
+template <class LatticeVal> void SparseSolver<LatticeVal>::Solve(Function &F) {
MarkBlockExecutable(&F.getEntryBlock());
// Process the work lists until they are empty!
@@ -331,7 +343,8 @@ void SparseSolver::Solve(Function &F) {
}
}
-void SparseSolver::Print(Function &F, raw_ostream &OS) const {
+template <class LatticeVal>
+void SparseSolver<LatticeVal>::Print(Function &F, raw_ostream &OS) const {
OS << "\nFUNCTION: " << F.getName() << "\n";
for (auto &BB : F) {
if (!BBExecutable.count(&BB))
More information about the llvm-commits
mailing list