[llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp
Owen Anderson
resistor at mac.com
Wed Jun 20 17:19:27 PDT 2007
Changes in directory llvm/lib/Transforms/Scalar:
GVNPRE.cpp updated: 1.46 -> 1.47
---
Log message:
Comment-ize the functions in GVNPRE.
---
Diffs of the changes: (+108 -76)
GVNPRE.cpp | 184 +++++++++++++++++++++++++++++++++++--------------------------
1 files changed, 108 insertions(+), 76 deletions(-)
Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp
diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.46 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.47
--- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.46 Wed Jun 20 17:10:02 2007
+++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Wed Jun 20 19:19:05 2007
@@ -42,7 +42,9 @@
// ValueTable Class
//===----------------------------------------------------------------------===//
-/// This class holds the mapping between values and value numbers.
+/// This class holds the mapping between values and value numbers. It is used
+/// as an efficient mechanism to determine the expression-wise equivalence of
+/// two values.
namespace {
class VISIBILITY_HIDDEN ValueTable {
@@ -89,6 +91,8 @@
Expression::ExpressionOpcode getOpcode(BinaryOperator* BO);
Expression::ExpressionOpcode getOpcode(CmpInst* C);
+ Expression create_expression(BinaryOperator* BO);
+ Expression create_expression(CmpInst* C);
public:
ValueTable() { nextValueNumber = 1; }
uint32_t lookup_or_add(Value* V);
@@ -100,14 +104,15 @@
}
std::set<Value*>& getMaximalValues() { return maximalValues; }
- Expression create_expression(BinaryOperator* BO);
- Expression create_expression(CmpInst* C);
void erase(Value* v);
};
}
+//===----------------------------------------------------------------------===//
+// ValueTable Internal Functions
+//===----------------------------------------------------------------------===//
ValueTable::Expression::ExpressionOpcode
- ValueTable::getOpcode(BinaryOperator* BO) {
+ ValueTable::getOpcode(BinaryOperator* BO) {
switch(BO->getOpcode()) {
case Instruction::Add:
return Expression::ADD;
@@ -215,6 +220,36 @@
}
}
+ValueTable::Expression ValueTable::create_expression(BinaryOperator* BO) {
+ Expression e;
+
+ e.leftVN = lookup_or_add(BO->getOperand(0));
+ e.rightVN = lookup_or_add(BO->getOperand(1));
+ e.opcode = getOpcode(BO);
+
+ maximalExpressions.insert(e);
+
+ return e;
+}
+
+ValueTable::Expression ValueTable::create_expression(CmpInst* C) {
+ Expression e;
+
+ e.leftVN = lookup_or_add(C->getOperand(0));
+ e.rightVN = lookup_or_add(C->getOperand(1));
+ e.opcode = getOpcode(C);
+
+ maximalExpressions.insert(e);
+
+ return e;
+}
+
+//===----------------------------------------------------------------------===//
+// ValueTable External Functions
+//===----------------------------------------------------------------------===//
+
+/// lookup_or_add - Returns the value number for the specified value, assigning
+/// it a new number if it did not have one before.
uint32_t ValueTable::lookup_or_add(Value* V) {
maximalValues.insert(V);
@@ -255,6 +290,8 @@
}
}
+/// lookup - Returns the value number of the specified value. Fails if
+/// the value has not yet been numbered.
uint32_t ValueTable::lookup(Value* V) {
DenseMap<Value*, uint32_t>::iterator VI = valueNumbering.find(V);
if (VI != valueNumbering.end())
@@ -265,6 +302,8 @@
return 0;
}
+/// add - Add the specified value with the given value number, removing
+/// its old number, if any
void ValueTable::add(Value* V, uint32_t num) {
DenseMap<Value*, uint32_t>::iterator VI = valueNumbering.find(V);
if (VI != valueNumbering.end())
@@ -272,30 +311,7 @@
valueNumbering.insert(std::make_pair(V, num));
}
-ValueTable::Expression ValueTable::create_expression(BinaryOperator* BO) {
- Expression e;
-
- e.leftVN = lookup_or_add(BO->getOperand(0));
- e.rightVN = lookup_or_add(BO->getOperand(1));
- e.opcode = getOpcode(BO);
-
- maximalExpressions.insert(e);
-
- return e;
-}
-
-ValueTable::Expression ValueTable::create_expression(CmpInst* C) {
- Expression e;
-
- e.leftVN = lookup_or_add(C->getOperand(0));
- e.rightVN = lookup_or_add(C->getOperand(1));
- e.opcode = getOpcode(C);
-
- maximalExpressions.insert(e);
-
- return e;
-}
-
+/// clear - Remove all entries from the ValueTable and the maximal sets
void ValueTable::clear() {
valueNumbering.clear();
expressionNumbering.clear();
@@ -304,6 +320,7 @@
nextValueNumber = 1;
}
+/// erase - Remove a value from the value numbering and maximal sets
void ValueTable::erase(Value* V) {
maximalValues.erase(V);
valueNumbering.erase(V);
@@ -313,6 +330,10 @@
maximalExpressions.erase(create_expression(C));
}
+//===----------------------------------------------------------------------===//
+// GVNPRE Pass
+//===----------------------------------------------------------------------===//
+
namespace {
class VISIBILITY_HIDDEN GVNPRE : public FunctionPass {
@@ -328,6 +349,7 @@
std::map<BasicBlock*, std::set<Value*> > availableOut;
std::map<BasicBlock*, std::set<Value*> > anticipatedIn;
+ // This transformation requires dominator postdominator info
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addRequired<DominatorTree>();
@@ -382,6 +404,7 @@
}
+// createGVNPREPass - The public interface to this file...
FunctionPass *llvm::createGVNPREPass() { return new GVNPRE(); }
RegisterPass<GVNPRE> X("gvnpre",
@@ -392,6 +415,9 @@
STATISTIC(NumInsertedPhis, "Number of PHI nodes inserted");
STATISTIC(NumEliminated, "Number of redundant instructions eliminated");
+/// find_leader - Given a set and a value number, return the first
+/// element of the set with that value number, or 0 if no such element
+/// is present
Value* GVNPRE::find_leader(std::set<Value*>& vals, uint32_t v) {
for (std::set<Value*>::iterator I = vals.begin(), E = vals.end();
I != E; ++I)
@@ -401,6 +427,8 @@
return 0;
}
+/// val_insert - Insert a value into a set only if there is not a value
+/// with the same value number already in the set
void GVNPRE::val_insert(std::set<Value*>& s, Value* v) {
uint32_t num = VN.lookup(v);
Value* leader = find_leader(s, num);
@@ -408,6 +436,8 @@
s.insert(v);
}
+/// val_replace - Insert a value into a set, replacing any values already in
+/// the set that have the same value number
void GVNPRE::val_replace(std::set<Value*>& s, Value* v) {
uint32_t num = VN.lookup(v);
Value* leader = find_leader(s, num);
@@ -418,6 +448,10 @@
s.insert(v);
}
+/// phi_translate - Given a value, its parent block, and a predecessor of its
+/// parent, translate the value into legal for the predecessor block. This
+/// means translating its operands (and recursively, their operands) through
+/// any phi nodes in the parent into values available in the predecessor
Value* GVNPRE::phi_translate(Value* V, BasicBlock* pred, BasicBlock* succ) {
if (V == 0)
return 0;
@@ -511,6 +545,7 @@
return V;
}
+/// phi_translate_set - Perform phi translation on every element of a set
void GVNPRE::phi_translate_set(std::set<Value*>& anticIn,
BasicBlock* pred, BasicBlock* succ,
std::set<Value*>& out) {
@@ -522,6 +557,9 @@
}
}
+/// dependsOnInvoke - Test if a value has an phi node as an operand, any of
+/// whose inputs is an invoke instruction. If this is true, we cannot safely
+/// PRE the instruction or anything that depends on it.
bool GVNPRE::dependsOnInvoke(Value* V) {
if (PHINode* p = dyn_cast<PHINode>(V)) {
for (PHINode::op_iterator I = p->op_begin(), E = p->op_end(); I != E; ++I)
@@ -533,7 +571,9 @@
}
}
-// Remove all expressions whose operands are not themselves in the set
+/// clean - Remove all non-opaque values from the set whose operands are not
+/// themselves in the set, as well as all values that depend on invokes (see
+/// above)
void GVNPRE::clean(std::set<Value*>& set) {
std::vector<Value*> worklist;
topo_sort(set, worklist);
@@ -595,8 +635,9 @@
}
}
-void GVNPRE::topo_sort(std::set<Value*>& set,
- std::vector<Value*>& vec) {
+/// topo_sort - Given a set of values, sort them by topological
+/// order into the provided vector.
+void GVNPRE::topo_sort(std::set<Value*>& set, std::vector<Value*>& vec) {
std::set<Value*> toErase;
for (std::set<Value*>::iterator I = set.begin(), E = set.end();
I != E; ++I) {
@@ -665,7 +706,7 @@
}
}
-
+/// dump - Dump a set of values to standard error
void GVNPRE::dump(const std::set<Value*>& s) const {
DOUT << "{ ";
for (std::set<Value*>::iterator I = s.begin(), E = s.end();
@@ -675,6 +716,9 @@
DOUT << "}\n\n";
}
+/// elimination - Phase 3 of the main algorithm. Perform full redundancy
+/// elimination by walking the dominator tree and removing any instruction that
+/// is dominated by another instruction with the same value number.
bool GVNPRE::elimination() {
DOUT << "\n\nPhase 3: Elimination\n\n";
@@ -724,7 +768,8 @@
return changed_function;
}
-
+/// cleanup - Delete any extraneous values that were created to represent
+/// expressions without leaders.
void GVNPRE::cleanup() {
while (!createdExpressions.empty()) {
Instruction* I = createdExpressions.back();
@@ -734,6 +779,8 @@
}
}
+/// buildsets_availout - When calculating availability, handle an instruction
+/// by inserting it into the appropriate sets
void GVNPRE::buildsets_availout(BasicBlock::iterator I,
std::set<Value*>& currAvail,
std::set<PHINode*>& currPhis,
@@ -780,6 +827,8 @@
val_insert(currAvail, I);
}
+/// buildsets_anticout - When walking the postdom tree, calculate the ANTIC_OUT
+/// set as a function of the ANTIC_IN set of the block's predecessors
void GVNPRE::buildsets_anticout(BasicBlock* BB,
std::set<Value*>& anticOut,
std::set<BasicBlock*>& visited) {
@@ -809,6 +858,9 @@
}
}
+/// buildsets_anticin - Walk the postdom tree, calculating ANTIC_OUT for
+/// each block. ANTIC_IN is then a function of ANTIC_OUT and the GEN
+/// sets populated in buildsets_availout
bool GVNPRE::buildsets_anticin(BasicBlock* BB,
std::set<Value*>& anticOut,
std::set<Value*>& currExps,
@@ -853,6 +905,8 @@
return false;
}
+/// buildsets - Phase 1 of the main algorithm. Construct the AVAIL_OUT
+/// and the ANTIC_IN sets.
unsigned GVNPRE::buildsets(Function& F) {
std::map<BasicBlock*, std::set<Value*> > generatedExpressions;
std::map<BasicBlock*, std::set<PHINode*> > generatedPhis;
@@ -926,38 +980,15 @@
iterations++;
}
- DOUT << "Iterations: " << iterations << "\n";
-
- for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
- DOUT << "Name: " << I->getName().c_str() << "\n";
-
- DOUT << "TMP_GEN: ";
- dump(generatedTemporaries[I]);
- DOUT << "\n";
-
- DOUT << "EXP_GEN: ";
- dump(generatedExpressions[I]);
- DOUT << "\n";
-
- DOUT << "ANTIC_IN: ";
- dump(anticipatedIn[I]);
- DOUT << "\n";
-
- DOUT << "AVAIL_OUT: ";
- dump(availableOut[I]);
- DOUT << "\n";
- }
-
return 0; // No bail, no changes
}
+/// insertion_pre - When a partial redundancy has been identified, eliminate it
+/// by inserting appropriate values into the predecessors and a phi node in
+/// the main block
void GVNPRE::insertion_pre(Value* e, BasicBlock* BB,
std::map<BasicBlock*, Value*>& avail,
std::set<Value*>& new_set) {
- DOUT << "Processing Value: ";
- DEBUG(e->dump());
- DOUT << "\n\n";
-
for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) {
Value* e2 = avail[*PI];
if (!find_leader(availableOut[*PI], VN.lookup(e2))) {
@@ -991,9 +1022,7 @@
std::set<Value*>& predAvail = availableOut[*PI];
val_replace(predAvail, newVal);
-
- DOUT << "Creating value: " << std::hex << newVal << std::dec << "\n";
-
+
std::map<BasicBlock*, Value*>::iterator av = avail.find(*PI);
if (av != avail.end())
avail.erase(av);
@@ -1013,24 +1042,14 @@
}
VN.add(p, VN.lookup(e));
- DOUT << "Creating value: " << std::hex << p << std::dec << "\n";
-
val_replace(availableOut[BB], p);
-
- DOUT << "Preds After Processing: ";
- for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI)
- DEBUG((*PI)->dump());
- DOUT << "\n\n";
-
- DOUT << "Merge Block After Processing: ";
- DEBUG(BB->dump());
- DOUT << "\n\n";
-
new_set.insert(p);
++NumInsertedPhis;
}
+/// insertion_mergepoint - When walking the dom tree, check at each merge
+/// block for the possibility of a partial redundancy. If present, eliminate it
unsigned GVNPRE::insertion_mergepoint(std::vector<Value*>& workList,
df_iterator<DomTreeNode*> D,
std::set<Value*>& new_set) {
@@ -1089,6 +1108,9 @@
return retval;
}
+/// insert - Phase 2 of the main algorithm. Walk the dominator tree looking for
+/// merge points. When one is found, check for a partial redundancy. If one is
+/// present, eliminate it. Repeat this walk until no changes are made.
bool GVNPRE::insertion(Function& F) {
bool changed_function = false;
@@ -1143,7 +1165,11 @@
return changed_function;
}
+// GVNPRE::runOnFunction - This is the main transformation entry point for a
+// function.
+//
bool GVNPRE::runOnFunction(Function &F) {
+ // Clean out global sets from any previous functions
VN.clear();
createdExpressions.clear();
availableOut.clear();
@@ -1152,20 +1178,26 @@
bool changed_function = false;
// Phase 1: BuildSets
+ // This phase calculates the AVAIL_OUT and ANTIC_IN sets
+ // NOTE: If full postdom information is no available, this will bail
+ // early, performing GVN but not PRE
unsigned bail = buildsets(F);
//If a bail occurred, terminate early
if (bail != 0)
return (bail == 2);
// Phase 2: Insert
- DOUT<< "\nPhase 2: Insertion\n";
-
+ // This phase inserts values to make partially redundant values
+ // fully redundant
changed_function |= insertion(F);
// Phase 3: Eliminate
+ // This phase performs trivial full redundancy elimination
changed_function |= elimination();
// Phase 4: Cleanup
+ // This phase cleans up values that were created solely
+ // as leaders for expressions
cleanup();
return changed_function;
More information about the llvm-commits
mailing list