[llvm-commits] CVS: llvm/lib/Transforms/Scalar/SCCP.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sun Nov 14 20:44:35 PST 2004
Changes in directory llvm/lib/Transforms/Scalar:
SCCP.cpp updated: 1.105 -> 1.106
---
Log message:
Substantially refactor the SCCP class into an SCCP pass and an SCCPSolver
class. The only changes are minor:
* Do not try to SCCP instructions that return void in the rewrite loop.
This is silly and fool hardy, wasting a map lookup and adding an entry
to the map which is never used.
* If we decide something has an undefined value, rewrite it to undef,
potentially leading to further simplications.
---
Diffs of the changes: (+210 -169)
Index: llvm/lib/Transforms/Scalar/SCCP.cpp
diff -u llvm/lib/Transforms/Scalar/SCCP.cpp:1.105 llvm/lib/Transforms/Scalar/SCCP.cpp:1.106
--- llvm/lib/Transforms/Scalar/SCCP.cpp:1.105 Wed Oct 27 11:12:28 2004
+++ llvm/lib/Transforms/Scalar/SCCP.cpp Sun Nov 14 22:44:20 2004
@@ -89,12 +89,11 @@
//===----------------------------------------------------------------------===//
-// SCCP Class
//
-// This class does all of the work of Sparse Conditional Constant Propagation.
-//
-namespace {
-class SCCP : public FunctionPass, public InstVisitor<SCCP> {
+/// SCCPSolver - This class is a general purpose solver for Sparse Conditional
+/// Constant Propagation.
+///
+class SCCPSolver : public InstVisitor<SCCPSolver> {
std::set<BasicBlock*> BBExecutable;// The basic blocks that are executable
hash_map<Value*, InstVal> ValueState; // The state each value is in...
@@ -121,22 +120,31 @@
std::set<Edge> KnownFeasibleEdges;
public:
- // runOnFunction - Run the Sparse Conditional Constant Propagation algorithm,
- // and return true if the function was modified.
- //
- bool runOnFunction(Function &F);
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesCFG();
+ /// 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 MarkBlockExecutable(BasicBlock *BB) {
+ DEBUG(std::cerr << "Marking Block Executable: " << BB->getName() << "\n");
+ BBExecutable.insert(BB); // Basic block is executable!
+ BBWorkList.push_back(BB); // Add the block to the work list!
+ }
+
+ /// Solve - Solve for constants and executable blocks.
+ ///
+ void Solve();
+
+ /// getExecutableBlocks - Once we have solved for constants, return the set of
+ /// blocks that is known to be executable.
+ std::set<BasicBlock*> &getExecutableBlocks() {
+ return BBExecutable;
+ }
+
+ /// getValueMapping - Once we have solved for constants, return the mapping of
+ /// LLVM values to InstVals.
+ hash_map<Value*, InstVal> &getValueMapping() {
+ return ValueState;
}
-
- //===--------------------------------------------------------------------===//
- // The implementation of this class
- //
private:
- friend struct InstVisitor<SCCP>; // Allow callbacks from visitor
-
// 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.
@@ -158,7 +166,8 @@
inline void markOverdefined(InstVal &IV, Instruction *I) {
if (IV.markOverdefined()) {
DEBUG(std::cerr << "markOverdefined: " << *I);
- OverdefinedInstWorkList.push_back(I); // Only instructions go on the work list
+ // Only instructions go on the work list
+ OverdefinedInstWorkList.push_back(I);
}
}
inline void markOverdefined(Instruction *I) {
@@ -206,12 +215,33 @@
}
} else {
- DEBUG(std::cerr << "Marking Block Executable: " << Dest->getName()<<"\n");
- BBExecutable.insert(Dest); // Basic block is executable!
- BBWorkList.push_back(Dest); // Add the block to the work list!
+ MarkBlockExecutable(Dest);
}
}
+ // getFeasibleSuccessors - Return a vector of booleans to indicate which
+ // successors are reachable from a given terminator instruction.
+ //
+ void getFeasibleSuccessors(TerminatorInst &TI, std::vector<bool> &Succs);
+
+ // isEdgeFeasible - Return true if the control flow edge from the 'From' basic
+ // block to the 'To' basic block is currently feasible...
+ //
+ bool isEdgeFeasible(BasicBlock *From, BasicBlock *To);
+
+ // OperandChangedState - This method is invoked on all of the users of an
+ // instruction that was just changed state somehow.... Based on this
+ // information, we need to update the specified user of this instruction.
+ //
+ void OperandChangedState(User *U) {
+ // Only instructions use other variable values!
+ Instruction &I = cast<Instruction>(*U);
+ if (BBExecutable.count(I.getParent())) // Inst is executable?
+ visit(I);
+ }
+
+private:
+ friend class InstVisitor<SCCPSolver>;
// visit implementations - Something changed in this instruction... Either an
// operand made a transition, or the instruction is newly executable. Change
@@ -249,149 +279,13 @@
std::cerr << "SCCP: Don't know how to handle: " << I;
markOverdefined(&I); // Just in case
}
-
- // getFeasibleSuccessors - Return a vector of booleans to indicate which
- // successors are reachable from a given terminator instruction.
- //
- void getFeasibleSuccessors(TerminatorInst &TI, std::vector<bool> &Succs);
-
- // isEdgeFeasible - Return true if the control flow edge from the 'From' basic
- // block to the 'To' basic block is currently feasible...
- //
- bool isEdgeFeasible(BasicBlock *From, BasicBlock *To);
-
- // OperandChangedState - This method is invoked on all of the users of an
- // instruction that was just changed state somehow.... Based on this
- // information, we need to update the specified user of this instruction.
- //
- void OperandChangedState(User *U) {
- // Only instructions use other variable values!
- Instruction &I = cast<Instruction>(*U);
- if (BBExecutable.count(I.getParent())) // Inst is executable?
- visit(I);
- }
};
- RegisterOpt<SCCP> X("sccp", "Sparse Conditional Constant Propagation");
-} // end anonymous namespace
-
-
-// createSCCPPass - This is the public interface to this file...
-FunctionPass *llvm::createSCCPPass() {
- return new SCCP();
-}
-
-
-//===----------------------------------------------------------------------===//
-// SCCP Class Implementation
-
-
-// runOnFunction() - Run the Sparse Conditional Constant Propagation algorithm,
-// and return true if the function was modified.
-//
-bool SCCP::runOnFunction(Function &F) {
- // Mark the first block of the function as being executable...
- BBExecutable.insert(F.begin()); // Basic block is executable!
- BBWorkList.push_back(F.begin()); // Add the block to the work list!
-
- // Process the work lists until they are empty!
- while (!BBWorkList.empty() || !InstWorkList.empty() ||
- !OverdefinedInstWorkList.empty()) {
- // Process the instruction work list...
- while (!OverdefinedInstWorkList.empty()) {
- Instruction *I = OverdefinedInstWorkList.back();
- OverdefinedInstWorkList.pop_back();
-
- DEBUG(std::cerr << "\nPopped off OI-WL: " << I);
-
- // "I" got into the work list because it either made the transition from
- // bottom to constant
- //
- // Anything on this worklist that is overdefined need not be visited
- // since all of its users will have already been marked as overdefined
- // Update all of the users of this instruction's value...
- //
- for_each(I->use_begin(), I->use_end(),
- bind_obj(this, &SCCP::OperandChangedState));
- }
- // Process the instruction work list...
- while (!InstWorkList.empty()) {
- Instruction *I = InstWorkList.back();
- InstWorkList.pop_back();
-
- DEBUG(std::cerr << "\nPopped off I-WL: " << *I);
-
- // "I" got into the work list because it either made the transition from
- // bottom to constant
- //
- // Anything on this worklist that is overdefined need not be visited
- // since all of its users will have already been marked as overdefined.
- // Update all of the users of this instruction's value...
- //
- InstVal &Ival = getValueState (I);
- if (!Ival.isOverdefined())
- for_each(I->use_begin(), I->use_end(),
- bind_obj(this, &SCCP::OperandChangedState));
- }
-
- // Process the basic block work list...
- while (!BBWorkList.empty()) {
- BasicBlock *BB = BBWorkList.back();
- BBWorkList.pop_back();
-
- DEBUG(std::cerr << "\nPopped off BBWL: " << *BB);
-
- // Notify all instructions in this basic block that they are newly
- // executable.
- visit(BB);
- }
- }
-
- DEBUG(for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
- if (!BBExecutable.count(I))
- std::cerr << "BasicBlock Dead:" << *I);
-
- // Iterate over all of the instructions in a function, replacing them with
- // constants if we have found them to be of constant values.
- //
- bool MadeChanges = false;
- for (Function::iterator BB = F.begin(), BBE = F.end(); BB != BBE; ++BB)
- for (BasicBlock::iterator BI = BB->begin(); BI != BB->end();) {
- Instruction &Inst = *BI;
- InstVal &IV = ValueState[&Inst];
- if (IV.isConstant()) {
- Constant *Const = IV.getConstant();
- DEBUG(std::cerr << "Constant: " << *Const << " = " << Inst);
-
- // Replaces all of the uses of a variable with uses of the constant.
- Inst.replaceAllUsesWith(Const);
-
- // Remove the operator from the list of definitions... and delete it.
- BI = BB->getInstList().erase(BI);
-
- // Hey, we just changed something!
- MadeChanges = true;
- ++NumInstRemoved;
- } else {
- ++BI;
- }
- }
-
- // Reset state so that the next invocation will have empty data structures
- BBExecutable.clear();
- ValueState.clear();
- std::vector<Instruction*>().swap(OverdefinedInstWorkList);
- std::vector<Instruction*>().swap(InstWorkList);
- std::vector<BasicBlock*>().swap(BBWorkList);
-
- return MadeChanges;
-}
-
-
// getFeasibleSuccessors - Return a vector of booleans to indicate which
// successors are reachable from a given terminator instruction.
//
-void SCCP::getFeasibleSuccessors(TerminatorInst &TI, std::vector<bool> &Succs) {
+void SCCPSolver::getFeasibleSuccessors(TerminatorInst &TI,
+ std::vector<bool> &Succs) {
Succs.resize(TI.getNumSuccessors());
if (BranchInst *BI = dyn_cast<BranchInst>(&TI)) {
if (BI->isUnconditional()) {
@@ -441,7 +335,7 @@
// isEdgeFeasible - Return true if the control flow edge from the 'From' basic
// block to the 'To' basic block is currently feasible...
//
-bool SCCP::isEdgeFeasible(BasicBlock *From, BasicBlock *To) {
+bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) {
assert(BBExecutable.count(To) && "Dest should always be alive!");
// Make sure the source basic block is executable!!
@@ -514,7 +408,7 @@
// 7. If a conditional branch has a value that is overdefined, make all
// successors executable.
//
-void SCCP::visitPHINode(PHINode &PN) {
+void SCCPSolver::visitPHINode(PHINode &PN) {
InstVal &PNIV = getValueState(&PN);
if (PNIV.isOverdefined()) {
// There may be instructions using this PHI node that are not overdefined
@@ -586,7 +480,7 @@
markConstant(PNIV, &PN, OperandVal); // Acquire operand value
}
-void SCCP::visitTerminatorInst(TerminatorInst &TI) {
+void SCCPSolver::visitTerminatorInst(TerminatorInst &TI) {
std::vector<bool> SuccFeasible;
getFeasibleSuccessors(TI, SuccFeasible);
@@ -598,7 +492,7 @@
markEdgeExecutable(BB, TI.getSuccessor(i));
}
-void SCCP::visitCastInst(CastInst &I) {
+void SCCPSolver::visitCastInst(CastInst &I) {
Value *V = I.getOperand(0);
InstVal &VState = getValueState(V);
if (VState.isOverdefined()) // Inherit overdefinedness of operand
@@ -607,7 +501,7 @@
markConstant(&I, ConstantExpr::getCast(VState.getConstant(), I.getType()));
}
-void SCCP::visitSelectInst(SelectInst &I) {
+void SCCPSolver::visitSelectInst(SelectInst &I) {
InstVal &CondValue = getValueState(I.getCondition());
if (CondValue.isOverdefined())
markOverdefined(&I);
@@ -630,7 +524,7 @@
}
// Handle BinaryOperators and Shift Instructions...
-void SCCP::visitBinaryOperator(Instruction &I) {
+void SCCPSolver::visitBinaryOperator(Instruction &I) {
InstVal &IV = ValueState[&I];
if (IV.isOverdefined()) return;
@@ -716,7 +610,7 @@
// Handle getelementptr instructions... if all operands are constants then we
// can turn this into a getelementptr ConstantExpr.
//
-void SCCP::visitGetElementPtrInst(GetElementPtrInst &I) {
+void SCCPSolver::visitGetElementPtrInst(GetElementPtrInst &I) {
InstVal &IV = ValueState[&I];
if (IV.isOverdefined()) return;
@@ -769,7 +663,7 @@
// Handle load instructions. If the operand is a constant pointer to a constant
// global, we can replace the load with the loaded constant value!
-void SCCP::visitLoadInst(LoadInst &I) {
+void SCCPSolver::visitLoadInst(LoadInst &I) {
InstVal &IV = ValueState[&I];
if (IV.isOverdefined()) return;
@@ -807,7 +701,7 @@
markOverdefined(IV, &I);
}
-void SCCP::visitCallInst(CallInst &I) {
+void SCCPSolver::visitCallInst(CallInst &I) {
InstVal &IV = ValueState[&I];
if (IV.isOverdefined()) return;
@@ -837,3 +731,150 @@
else
markOverdefined(IV, &I);
}
+
+
+void SCCPSolver::Solve() {
+ // Process the work lists until they are empty!
+ while (!BBWorkList.empty() || !InstWorkList.empty() ||
+ !OverdefinedInstWorkList.empty()) {
+ // Process the instruction work list...
+ while (!OverdefinedInstWorkList.empty()) {
+ Instruction *I = OverdefinedInstWorkList.back();
+ OverdefinedInstWorkList.pop_back();
+
+ DEBUG(std::cerr << "\nPopped off OI-WL: " << I);
+
+ // "I" got into the work list because it either made the transition from
+ // bottom to constant
+ //
+ // Anything on this worklist that is overdefined need not be visited
+ // since all of its users will have already been marked as overdefined
+ // Update all of the users of this instruction's value...
+ //
+ for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
+ UI != E; ++UI)
+ OperandChangedState(*UI);
+ }
+ // Process the instruction work list...
+ while (!InstWorkList.empty()) {
+ Instruction *I = InstWorkList.back();
+ InstWorkList.pop_back();
+
+ DEBUG(std::cerr << "\nPopped off I-WL: " << *I);
+
+ // "I" got into the work list because it either made the transition from
+ // bottom to constant
+ //
+ // Anything on this worklist that is overdefined need not be visited
+ // since all of its users will have already been marked as overdefined.
+ // Update all of the users of this instruction's value...
+ //
+ if (!getValueState(I).isOverdefined())
+ for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
+ UI != E; ++UI)
+ OperandChangedState(*UI);
+ }
+
+ // Process the basic block work list...
+ while (!BBWorkList.empty()) {
+ BasicBlock *BB = BBWorkList.back();
+ BBWorkList.pop_back();
+
+ DEBUG(std::cerr << "\nPopped off BBWL: " << *BB);
+
+ // Notify all instructions in this basic block that they are newly
+ // executable.
+ visit(BB);
+ }
+ }
+}
+
+
+namespace {
+//===----------------------------------------------------------------------===//
+//
+/// SCCP Class - This class does all of the work of Sparse Conditional Constant
+/// Propagation.
+///
+class SCCP : public FunctionPass, public InstVisitor<SCCP> {
+public:
+
+ // runOnFunction - Run the Sparse Conditional Constant Propagation algorithm,
+ // and return true if the function was modified.
+ //
+ bool runOnFunction(Function &F);
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesCFG();
+ }
+};
+
+ RegisterOpt<SCCP> X("sccp", "Sparse Conditional Constant Propagation");
+} // end anonymous namespace
+
+
+// createSCCPPass - This is the public interface to this file...
+FunctionPass *llvm::createSCCPPass() {
+ return new SCCP();
+}
+
+
+//===----------------------------------------------------------------------===//
+// SCCP Class Implementation
+
+
+// runOnFunction() - Run the Sparse Conditional Constant Propagation algorithm,
+// and return true if the function was modified.
+//
+bool SCCP::runOnFunction(Function &F) {
+ SCCPSolver Solver;
+
+ // Mark the first block of the function as being executable.
+ Solver.MarkBlockExecutable(F.begin());
+
+ // Solve for constants.
+ Solver.Solve();
+
+ DEBUG(std::cerr << "SCCP on function '" << F.getName() << "'\n");
+ DEBUG(std::set<BasicBlock*> &ExecutableBBs = Solver.getExecutableBlocks();
+ for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
+ if (!ExecutableBBs.count(I))
+ std::cerr << " BasicBlock Dead:" << *I);
+
+ // Iterate over all of the instructions in a function, replacing them with
+ // constants if we have found them to be of constant values.
+ //
+ bool MadeChanges = false;
+ hash_map<Value*, InstVal> &Values = Solver.getValueMapping();
+ for (Function::iterator BB = F.begin(), BBE = F.end(); BB != BBE; ++BB)
+ for (BasicBlock::iterator BI = BB->begin(), E = BB->end(); BI != E; ) {
+ Instruction *Inst = BI++;
+ if (Inst->getType() != Type::VoidTy) {
+ InstVal &IV = Values[Inst];
+ if (IV.isConstant() || IV.isUndefined()) {
+ Constant *Const;
+ if (IV.isConstant()) {
+ Const = IV.getConstant();
+ DEBUG(std::cerr << " Constant: " << *Const << " = " << *Inst);
+ } else {
+ Const = UndefValue::get(Inst->getType());
+ DEBUG(std::cerr << " Undefined: " << *Inst);
+ }
+
+ // Replaces all of the uses of a variable with uses of the constant.
+ Inst->replaceAllUsesWith(Const);
+
+ // Delete the instruction.
+ BB->getInstList().erase(Inst);
+
+ // Hey, we just changed something!
+ MadeChanges = true;
+ ++NumInstRemoved;
+ }
+ }
+ }
+
+ return MadeChanges;
+}
+
+
More information about the llvm-commits
mailing list