mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
1) Fix an issue with non-deterministic iteration order in phi_translate
2) Remove some maximal-set computing code that is no longer used. 3) Use a post-order CFG traversal to compute ANTIC_IN instead of a postdom traversal. This causes the ANTIC_IN calculation to converge much faster. Thanks to Daniel Berlin for suggesting this. With this patch, the time to optimize 403.gcc decreased from 17.5s to 7.5s, and Anton's huge testcase decreased from 62 minutes to 38 seconds. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37714 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4390feb7ae
commit
f62c44a38d
@ -24,7 +24,6 @@
|
|||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/Analysis/Dominators.h"
|
#include "llvm/Analysis/Dominators.h"
|
||||||
#include "llvm/Analysis/PostDominators.h"
|
|
||||||
#include "llvm/ADT/BitVector.h"
|
#include "llvm/ADT/BitVector.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/DepthFirstIterator.h"
|
#include "llvm/ADT/DepthFirstIterator.h"
|
||||||
@ -86,9 +85,6 @@ namespace {
|
|||||||
DenseMap<Value*, uint32_t> valueNumbering;
|
DenseMap<Value*, uint32_t> valueNumbering;
|
||||||
std::map<Expression, uint32_t> expressionNumbering;
|
std::map<Expression, uint32_t> expressionNumbering;
|
||||||
|
|
||||||
std::set<Expression> maximalExpressions;
|
|
||||||
SmallPtrSet<Value*, 32> maximalValues;
|
|
||||||
|
|
||||||
uint32_t nextValueNumber;
|
uint32_t nextValueNumber;
|
||||||
|
|
||||||
Expression::ExpressionOpcode getOpcode(BinaryOperator* BO);
|
Expression::ExpressionOpcode getOpcode(BinaryOperator* BO);
|
||||||
@ -101,11 +97,6 @@ namespace {
|
|||||||
uint32_t lookup(Value* V);
|
uint32_t lookup(Value* V);
|
||||||
void add(Value* V, uint32_t num);
|
void add(Value* V, uint32_t num);
|
||||||
void clear();
|
void clear();
|
||||||
std::set<Expression>& getMaximalExpressions() {
|
|
||||||
return maximalExpressions;
|
|
||||||
|
|
||||||
}
|
|
||||||
SmallPtrSet<Value*, 32>& getMaximalValues() { return maximalValues; }
|
|
||||||
void erase(Value* v);
|
void erase(Value* v);
|
||||||
unsigned size();
|
unsigned size();
|
||||||
};
|
};
|
||||||
@ -230,8 +221,6 @@ ValueTable::Expression ValueTable::create_expression(BinaryOperator* BO) {
|
|||||||
e.rightVN = lookup_or_add(BO->getOperand(1));
|
e.rightVN = lookup_or_add(BO->getOperand(1));
|
||||||
e.opcode = getOpcode(BO);
|
e.opcode = getOpcode(BO);
|
||||||
|
|
||||||
maximalExpressions.insert(e);
|
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,8 +231,6 @@ ValueTable::Expression ValueTable::create_expression(CmpInst* C) {
|
|||||||
e.rightVN = lookup_or_add(C->getOperand(1));
|
e.rightVN = lookup_or_add(C->getOperand(1));
|
||||||
e.opcode = getOpcode(C);
|
e.opcode = getOpcode(C);
|
||||||
|
|
||||||
maximalExpressions.insert(e);
|
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,8 +241,6 @@ ValueTable::Expression ValueTable::create_expression(CmpInst* C) {
|
|||||||
/// lookup_or_add - Returns the value number for the specified value, assigning
|
/// lookup_or_add - Returns the value number for the specified value, assigning
|
||||||
/// it a new number if it did not have one before.
|
/// it a new number if it did not have one before.
|
||||||
uint32_t ValueTable::lookup_or_add(Value* V) {
|
uint32_t ValueTable::lookup_or_add(Value* V) {
|
||||||
maximalValues.insert(V);
|
|
||||||
|
|
||||||
DenseMap<Value*, uint32_t>::iterator VI = valueNumbering.find(V);
|
DenseMap<Value*, uint32_t>::iterator VI = valueNumbering.find(V);
|
||||||
if (VI != valueNumbering.end())
|
if (VI != valueNumbering.end())
|
||||||
return VI->second;
|
return VI->second;
|
||||||
@ -314,23 +299,16 @@ void ValueTable::add(Value* V, uint32_t num) {
|
|||||||
valueNumbering.insert(std::make_pair(V, num));
|
valueNumbering.insert(std::make_pair(V, num));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// clear - Remove all entries from the ValueTable and the maximal sets
|
/// clear - Remove all entries from the ValueTable
|
||||||
void ValueTable::clear() {
|
void ValueTable::clear() {
|
||||||
valueNumbering.clear();
|
valueNumbering.clear();
|
||||||
expressionNumbering.clear();
|
expressionNumbering.clear();
|
||||||
maximalExpressions.clear();
|
|
||||||
maximalValues.clear();
|
|
||||||
nextValueNumber = 1;
|
nextValueNumber = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// erase - Remove a value from the value numbering and maximal sets
|
/// erase - Remove a value from the value numbering
|
||||||
void ValueTable::erase(Value* V) {
|
void ValueTable::erase(Value* V) {
|
||||||
maximalValues.erase(V);
|
|
||||||
valueNumbering.erase(V);
|
valueNumbering.erase(V);
|
||||||
if (BinaryOperator* BO = dyn_cast<BinaryOperator>(V))
|
|
||||||
maximalExpressions.erase(create_expression(BO));
|
|
||||||
else if (CmpInst* C = dyn_cast<CmpInst>(V))
|
|
||||||
maximalExpressions.erase(create_expression(C));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// size - Return the number of assigned value numbers
|
/// size - Return the number of assigned value numbers
|
||||||
@ -362,7 +340,6 @@ namespace {
|
|||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.setPreservesCFG();
|
AU.setPreservesCFG();
|
||||||
AU.addRequired<DominatorTree>();
|
AU.addRequired<DominatorTree>();
|
||||||
AU.addRequired<PostDominatorTree>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper fuctions
|
// Helper fuctions
|
||||||
@ -467,33 +444,38 @@ Value* GVNPRE::phi_translate(Value* V, BasicBlock* pred, BasicBlock* succ) {
|
|||||||
if (V == 0)
|
if (V == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (BinaryOperator* BO = dyn_cast<BinaryOperator>(V)) {
|
if (isa<BinaryOperator>(V) || isa<CmpInst>(V)) {
|
||||||
|
User* U = cast<User>(V);
|
||||||
|
|
||||||
Value* newOp1 = 0;
|
Value* newOp1 = 0;
|
||||||
if (isa<Instruction>(BO->getOperand(0)))
|
if (isa<Instruction>(U->getOperand(0)))
|
||||||
newOp1 = phi_translate(find_leader(anticipatedIn[succ],
|
newOp1 = phi_translate(U->getOperand(0), pred, succ);
|
||||||
VN.lookup(BO->getOperand(0))),
|
|
||||||
pred, succ);
|
|
||||||
else
|
else
|
||||||
newOp1 = BO->getOperand(0);
|
newOp1 = U->getOperand(0);
|
||||||
|
|
||||||
if (newOp1 == 0)
|
if (newOp1 == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Value* newOp2 = 0;
|
Value* newOp2 = 0;
|
||||||
if (isa<Instruction>(BO->getOperand(1)))
|
if (isa<Instruction>(U->getOperand(1)))
|
||||||
newOp2 = phi_translate(find_leader(anticipatedIn[succ],
|
newOp2 = phi_translate(U->getOperand(1), pred, succ);
|
||||||
VN.lookup(BO->getOperand(1))),
|
|
||||||
pred, succ);
|
|
||||||
else
|
else
|
||||||
newOp2 = BO->getOperand(1);
|
newOp2 = U->getOperand(1);
|
||||||
|
|
||||||
if (newOp2 == 0)
|
if (newOp2 == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (newOp1 != BO->getOperand(0) || newOp2 != BO->getOperand(1)) {
|
if (newOp1 != U->getOperand(0) || newOp2 != U->getOperand(1)) {
|
||||||
Instruction* newVal = BinaryOperator::create(BO->getOpcode(),
|
Instruction* newVal = 0;
|
||||||
newOp1, newOp2,
|
if (BinaryOperator* BO = dyn_cast<BinaryOperator>(U))
|
||||||
BO->getName()+".expr");
|
newVal = BinaryOperator::create(BO->getOpcode(),
|
||||||
|
newOp1, newOp2,
|
||||||
|
BO->getName()+".expr");
|
||||||
|
else if (CmpInst* C = dyn_cast<CmpInst>(U))
|
||||||
|
newVal = CmpInst::create(C->getOpcode(),
|
||||||
|
C->getPredicate(),
|
||||||
|
newOp1, newOp2,
|
||||||
|
C->getName()+".expr");
|
||||||
|
|
||||||
uint32_t v = VN.lookup_or_add(newVal);
|
uint32_t v = VN.lookup_or_add(newVal);
|
||||||
|
|
||||||
@ -510,47 +492,6 @@ Value* GVNPRE::phi_translate(Value* V, BasicBlock* pred, BasicBlock* succ) {
|
|||||||
} else if (PHINode* P = dyn_cast<PHINode>(V)) {
|
} else if (PHINode* P = dyn_cast<PHINode>(V)) {
|
||||||
if (P->getParent() == succ)
|
if (P->getParent() == succ)
|
||||||
return P->getIncomingValueForBlock(pred);
|
return P->getIncomingValueForBlock(pred);
|
||||||
} else if (CmpInst* C = dyn_cast<CmpInst>(V)) {
|
|
||||||
Value* newOp1 = 0;
|
|
||||||
if (isa<Instruction>(C->getOperand(0)))
|
|
||||||
newOp1 = phi_translate(find_leader(anticipatedIn[succ],
|
|
||||||
VN.lookup(C->getOperand(0))),
|
|
||||||
pred, succ);
|
|
||||||
else
|
|
||||||
newOp1 = C->getOperand(0);
|
|
||||||
|
|
||||||
if (newOp1 == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
Value* newOp2 = 0;
|
|
||||||
if (isa<Instruction>(C->getOperand(1)))
|
|
||||||
newOp2 = phi_translate(find_leader(anticipatedIn[succ],
|
|
||||||
VN.lookup(C->getOperand(1))),
|
|
||||||
pred, succ);
|
|
||||||
else
|
|
||||||
newOp2 = C->getOperand(1);
|
|
||||||
|
|
||||||
if (newOp2 == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (newOp1 != C->getOperand(0) || newOp2 != C->getOperand(1)) {
|
|
||||||
Instruction* newVal = CmpInst::create(C->getOpcode(),
|
|
||||||
C->getPredicate(),
|
|
||||||
newOp1, newOp2,
|
|
||||||
C->getName()+".expr");
|
|
||||||
|
|
||||||
uint32_t v = VN.lookup_or_add(newVal);
|
|
||||||
|
|
||||||
Value* leader = find_leader(availableOut[pred], v);
|
|
||||||
if (leader == 0) {
|
|
||||||
createdExpressions.push_back(newVal);
|
|
||||||
return newVal;
|
|
||||||
} else {
|
|
||||||
VN.erase(newVal);
|
|
||||||
delete newVal;
|
|
||||||
return leader;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return V;
|
return V;
|
||||||
@ -728,9 +669,9 @@ bool GVNPRE::elimination() {
|
|||||||
E = df_end(DT.getRootNode()); DI != E; ++DI) {
|
E = df_end(DT.getRootNode()); DI != E; ++DI) {
|
||||||
BasicBlock* BB = DI->getBlock();
|
BasicBlock* BB = DI->getBlock();
|
||||||
|
|
||||||
DOUT << "Block: " << BB->getName() << "\n";
|
//DOUT << "Block: " << BB->getName() << "\n";
|
||||||
dump(availableOut[BB]);
|
//dump(availableOut[BB]);
|
||||||
DOUT << "\n\n";
|
//DOUT << "\n\n";
|
||||||
|
|
||||||
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
|
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
|
||||||
BI != BE; ++BI) {
|
BI != BE; ++BI) {
|
||||||
@ -866,11 +807,15 @@ bool GVNPRE::buildsets_anticout(BasicBlock* BB,
|
|||||||
SmallPtrSet<Value*, 32>& anticOut,
|
SmallPtrSet<Value*, 32>& anticOut,
|
||||||
std::set<BasicBlock*>& visited) {
|
std::set<BasicBlock*>& visited) {
|
||||||
if (BB->getTerminator()->getNumSuccessors() == 1) {
|
if (BB->getTerminator()->getNumSuccessors() == 1) {
|
||||||
if (visited.count(BB->getTerminator()->getSuccessor(0)) == 0)
|
if (BB->getTerminator()->getSuccessor(0) != BB &&
|
||||||
|
visited.count(BB->getTerminator()->getSuccessor(0)) == 0) {
|
||||||
|
DOUT << "DEFER: " << BB->getName() << "\n";
|
||||||
return true;
|
return true;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
phi_translate_set(anticipatedIn[BB->getTerminator()->getSuccessor(0)],
|
phi_translate_set(anticipatedIn[BB->getTerminator()->getSuccessor(0)],
|
||||||
BB, BB->getTerminator()->getSuccessor(0), anticOut);
|
BB, BB->getTerminator()->getSuccessor(0), anticOut);
|
||||||
|
}
|
||||||
} else if (BB->getTerminator()->getNumSuccessors() > 1) {
|
} else if (BB->getTerminator()->getNumSuccessors() > 1) {
|
||||||
BasicBlock* first = BB->getTerminator()->getSuccessor(0);
|
BasicBlock* first = BB->getTerminator()->getSuccessor(0);
|
||||||
anticOut.insert(anticipatedIn[first].begin(), anticipatedIn[first].end());
|
anticOut.insert(anticipatedIn[first].begin(), anticipatedIn[first].end());
|
||||||
@ -910,13 +855,17 @@ unsigned GVNPRE::buildsets_anticin(BasicBlock* BB,
|
|||||||
if (defer)
|
if (defer)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
anticIn.clear();
|
anticIn.clear();
|
||||||
|
|
||||||
BitVector numbers(VN.size());
|
BitVector numbers(VN.size());
|
||||||
for (SmallPtrSet<Value*, 32>::iterator I = anticOut.begin(),
|
for (SmallPtrSet<Value*, 32>::iterator I = anticOut.begin(),
|
||||||
E = anticOut.end(); I != E; ++I) {
|
E = anticOut.end(); I != E; ++I) {
|
||||||
anticIn.insert(*I);
|
anticIn.insert(*I);
|
||||||
numbers.set(VN.lookup_or_add(*I));
|
unsigned num = VN.lookup_or_add(*I);
|
||||||
|
numbers.resize(VN.size());
|
||||||
|
numbers.set(num);
|
||||||
}
|
}
|
||||||
for (SmallPtrSet<Value*, 32>::iterator I = currExps.begin(),
|
for (SmallPtrSet<Value*, 32>::iterator I = currExps.begin(),
|
||||||
E = currExps.end(); I != E; ++I) {
|
E = currExps.end(); I != E; ++I) {
|
||||||
@ -931,11 +880,15 @@ unsigned GVNPRE::buildsets_anticin(BasicBlock* BB,
|
|||||||
anticIn.erase(*I);
|
anticIn.erase(*I);
|
||||||
|
|
||||||
clean(anticIn);
|
clean(anticIn);
|
||||||
anticOut.clear();
|
|
||||||
|
|
||||||
if (old != anticIn.size())
|
if (old != anticIn.size()) {
|
||||||
|
DOUT << "OLD: " << old << "\n";
|
||||||
|
DOUT << "NEW: " << anticIn.size() << "\n";
|
||||||
|
DOUT << "ANTIC_OUT: " << anticOut.size() << "\n";
|
||||||
|
anticOut.clear();
|
||||||
return 2;
|
return 2;
|
||||||
else
|
} else
|
||||||
|
anticOut.clear();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -979,21 +932,41 @@ unsigned GVNPRE::buildsets(Function& F) {
|
|||||||
currTemps, availNumbers, expNumbers);
|
currTemps, availNumbers, expNumbers);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Phase 1, Part 2: calculate ANTIC_IN
|
||||||
|
|
||||||
// If function has no exit blocks, only perform GVN
|
DOUT << "Calculating walk\n";
|
||||||
PostDominatorTree &PDT = getAnalysis<PostDominatorTree>();
|
// Calculate a postorder CFG walk
|
||||||
if (PDT[&F.getEntryBlock()] == 0) {
|
std::vector<BasicBlock*> walk;
|
||||||
bool changed_function = elimination();
|
std::vector<BasicBlock*> walkStack;
|
||||||
cleanup();
|
SmallPtrSet<BasicBlock*, 16> walkVisited;
|
||||||
|
walkStack.push_back(&F.getEntryBlock());
|
||||||
|
walkVisited.insert(&F.getEntryBlock());
|
||||||
|
|
||||||
|
while (!walkStack.empty()) {
|
||||||
|
BasicBlock* BB = walkStack.back();
|
||||||
|
walkVisited.insert(BB);
|
||||||
|
|
||||||
if (changed_function)
|
bool inserted = false;
|
||||||
return 2; // Bailed early, made changes
|
for (unsigned i = 0; i < BB->getTerminator()->getNumSuccessors(); ++i) {
|
||||||
else
|
BasicBlock* succ = BB->getTerminator()->getSuccessor(i);
|
||||||
return 1; // Bailed early, no changes
|
if (walkVisited.count(succ) == 0) {
|
||||||
|
walkStack.push_back(succ);
|
||||||
|
inserted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inserted)
|
||||||
|
continue;
|
||||||
|
else {
|
||||||
|
walk.push_back(BB);
|
||||||
|
walkStack.pop_back();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DOUT << "Finished calculating walk\n";
|
||||||
|
|
||||||
// Phase 1, Part 2: calculate ANTIC_IN
|
// Perform the ANTIC_IN calculation
|
||||||
|
|
||||||
std::set<BasicBlock*> visited;
|
std::set<BasicBlock*> visited;
|
||||||
|
|
||||||
@ -1004,23 +977,23 @@ unsigned GVNPRE::buildsets(Function& F) {
|
|||||||
SmallPtrSet<Value*, 32> anticOut;
|
SmallPtrSet<Value*, 32> anticOut;
|
||||||
|
|
||||||
// Top-down walk of the postdominator tree
|
// Top-down walk of the postdominator tree
|
||||||
for (df_iterator<DomTreeNode*> PDI =
|
for (std::vector<BasicBlock*>::iterator BBI = walk.begin(), BBE = walk.end();
|
||||||
df_begin(PDT.getRootNode()), E = df_end(PDT.getRootNode());
|
BBI != BBE; ++BBI) {
|
||||||
PDI != E; ++PDI) {
|
BasicBlock* BB = *BBI;
|
||||||
BasicBlock* BB = PDI->getBlock();
|
|
||||||
if (BB == 0)
|
if (BB == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned ret = buildsets_anticin(BB, anticOut,generatedExpressions[BB],
|
unsigned ret = buildsets_anticin(BB, anticOut,generatedExpressions[BB],
|
||||||
generatedTemporaries[BB], visited);
|
generatedTemporaries[BB], visited);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
changed = true;
|
changed = true;
|
||||||
break;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
visited.insert(BB);
|
visited.insert(BB);
|
||||||
|
if (ret == 2) {
|
||||||
|
DOUT << "CHANGED: " << BB->getName() << "\n";
|
||||||
|
}
|
||||||
changed |= (ret == 2);
|
changed |= (ret == 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1028,6 +1001,8 @@ unsigned GVNPRE::buildsets(Function& F) {
|
|||||||
iterations++;
|
iterations++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DOUT << "ITERATIONS: " << iterations << "\n";
|
||||||
|
|
||||||
return 0; // No bail, no changes
|
return 0; // No bail, no changes
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1197,10 +1172,10 @@ bool GVNPRE::insertion(Function& F) {
|
|||||||
workList.reserve(anticIn.size());
|
workList.reserve(anticIn.size());
|
||||||
topo_sort(anticIn, workList);
|
topo_sort(anticIn, workList);
|
||||||
|
|
||||||
DOUT << "Merge Block: " << BB->getName() << "\n";
|
//DOUT << "Merge Block: " << BB->getName() << "\n";
|
||||||
DOUT << "ANTIC_IN: ";
|
//DOUT << "ANTIC_IN: ";
|
||||||
dump(anticIn);
|
//dump(anticIn);
|
||||||
DOUT << "\n";
|
//DOUT << "\n";
|
||||||
|
|
||||||
unsigned result = insertion_mergepoint(workList, DI, new_set);
|
unsigned result = insertion_mergepoint(workList, DI, new_set);
|
||||||
if (result & 1)
|
if (result & 1)
|
||||||
|
Loading…
Reference in New Issue
Block a user