mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Switch GVN to use ScopedHashTable.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52242 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2c3d949253
commit
af4240ac2d
@ -25,6 +25,7 @@
|
|||||||
#include "llvm/Value.h"
|
#include "llvm/Value.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/DepthFirstIterator.h"
|
#include "llvm/ADT/DepthFirstIterator.h"
|
||||||
|
#include "llvm/ADT/ScopedHashTable.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/SparseBitVector.h"
|
#include "llvm/ADT/SparseBitVector.h"
|
||||||
@ -666,55 +667,25 @@ void ValueTable::erase(Value* V) {
|
|||||||
valueNumbering.erase(V);
|
valueNumbering.erase(V);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// ValueNumberedSet Class
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
namespace {
|
|
||||||
class VISIBILITY_HIDDEN ValueNumberedSet {
|
|
||||||
private:
|
|
||||||
SmallPtrSet<Value*, 8> contents;
|
|
||||||
SparseBitVector<64> numbers;
|
|
||||||
public:
|
|
||||||
ValueNumberedSet() { }
|
|
||||||
ValueNumberedSet(const ValueNumberedSet& other) {
|
|
||||||
numbers = other.numbers;
|
|
||||||
contents = other.contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef SmallPtrSet<Value*, 8>::iterator iterator;
|
|
||||||
|
|
||||||
iterator begin() { return contents.begin(); }
|
|
||||||
iterator end() { return contents.end(); }
|
|
||||||
|
|
||||||
bool insert(Value* v) { return contents.insert(v); }
|
|
||||||
void insert(iterator I, iterator E) { contents.insert(I, E); }
|
|
||||||
void erase(Value* v) { contents.erase(v); }
|
|
||||||
unsigned count(Value* v) { return contents.count(v); }
|
|
||||||
size_t size() { return contents.size(); }
|
|
||||||
|
|
||||||
void set(unsigned i) {
|
|
||||||
numbers.set(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator=(const ValueNumberedSet& other) {
|
|
||||||
contents = other.contents;
|
|
||||||
numbers = other.numbers;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset(unsigned i) {
|
|
||||||
numbers.reset(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool test(unsigned i) {
|
|
||||||
return numbers.test(i);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// GVN Pass
|
// GVN Pass
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
template<> struct DenseMapInfo<uint32_t> {
|
||||||
|
static inline uint32_t getEmptyKey() { return ~0; }
|
||||||
|
static inline uint32_t getTombstoneKey() { return ~0 - 1; }
|
||||||
|
static unsigned getHashValue(const uint32_t& Val) { return Val; }
|
||||||
|
static bool isPod() { return true; }
|
||||||
|
static bool isEqual(const uint32_t& LHS, const uint32_t& RHS) {
|
||||||
|
return LHS == RHS;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ScopedHashTable<uint32_t, Value*> ValueNumberMap;
|
||||||
|
typedef ScopedHashTableScope<uint32_t, Value*> ValueNumberScope;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class VISIBILITY_HIDDEN GVN : public FunctionPass {
|
class VISIBILITY_HIDDEN GVN : public FunctionPass {
|
||||||
@ -726,7 +697,8 @@ namespace {
|
|||||||
private:
|
private:
|
||||||
ValueTable VN;
|
ValueTable VN;
|
||||||
|
|
||||||
DenseMap<BasicBlock*, ValueNumberedSet> availableOut;
|
DenseMap<BasicBlock*, ValueNumberScope> availableOut;
|
||||||
|
ValueNumberMap BaseMap;
|
||||||
|
|
||||||
typedef DenseMap<Value*, SmallPtrSet<Instruction*, 4> > PhiMapType;
|
typedef DenseMap<Value*, SmallPtrSet<Instruction*, 4> > PhiMapType;
|
||||||
PhiMapType phiMap;
|
PhiMapType phiMap;
|
||||||
@ -744,17 +716,15 @@ namespace {
|
|||||||
|
|
||||||
// Helper fuctions
|
// Helper fuctions
|
||||||
// FIXME: eliminate or document these better
|
// FIXME: eliminate or document these better
|
||||||
Value* find_leader(ValueNumberedSet& vals, uint32_t v) ;
|
|
||||||
void val_insert(ValueNumberedSet& s, Value* v);
|
|
||||||
bool processLoad(LoadInst* L,
|
bool processLoad(LoadInst* L,
|
||||||
DenseMap<Value*, LoadInst*> &lastLoad,
|
DenseMap<Value*, LoadInst*> &lastLoad,
|
||||||
SmallVectorImpl<Instruction*> &toErase);
|
SmallVectorImpl<Instruction*> &toErase);
|
||||||
bool processInstruction(Instruction* I,
|
bool processInstruction(Instruction* I,
|
||||||
ValueNumberedSet& currAvail,
|
|
||||||
DenseMap<Value*, LoadInst*>& lastSeenLoad,
|
DenseMap<Value*, LoadInst*>& lastSeenLoad,
|
||||||
SmallVectorImpl<Instruction*> &toErase);
|
SmallVectorImpl<Instruction*> &toErase);
|
||||||
bool processNonLocalLoad(LoadInst* L,
|
bool processNonLocalLoad(LoadInst* L,
|
||||||
SmallVectorImpl<Instruction*> &toErase);
|
SmallVectorImpl<Instruction*> &toErase);
|
||||||
|
bool processBlock(DomTreeNode* DTN);
|
||||||
Value *GetValueForBlock(BasicBlock *BB, LoadInst* orig,
|
Value *GetValueForBlock(BasicBlock *BB, LoadInst* orig,
|
||||||
DenseMap<BasicBlock*, Value*> &Phis,
|
DenseMap<BasicBlock*, Value*> &Phis,
|
||||||
bool top_level = false);
|
bool top_level = false);
|
||||||
@ -773,30 +743,6 @@ FunctionPass *llvm::createGVNPass() { return new GVN(); }
|
|||||||
static RegisterPass<GVN> X("gvn",
|
static RegisterPass<GVN> X("gvn",
|
||||||
"Global Value Numbering");
|
"Global Value Numbering");
|
||||||
|
|
||||||
/// 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* GVN::find_leader(ValueNumberedSet& vals, uint32_t v) {
|
|
||||||
if (!vals.test(v))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (ValueNumberedSet::iterator I = vals.begin(), E = vals.end();
|
|
||||||
I != E; ++I)
|
|
||||||
if (v == VN.lookup(*I))
|
|
||||||
return *I;
|
|
||||||
|
|
||||||
assert(0 && "No leader found, but present bit is set?");
|
|
||||||
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 GVN::val_insert(ValueNumberedSet& s, Value* v) {
|
|
||||||
uint32_t num = VN.lookup(v);
|
|
||||||
if (!s.test(num))
|
|
||||||
s.insert(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GVN::dump(DenseMap<BasicBlock*, Value*>& d) {
|
void GVN::dump(DenseMap<BasicBlock*, Value*>& d) {
|
||||||
printf("{\n");
|
printf("{\n");
|
||||||
for (DenseMap<BasicBlock*, Value*>::iterator I = d.begin(),
|
for (DenseMap<BasicBlock*, Value*>::iterator I = d.begin(),
|
||||||
@ -1061,7 +1007,7 @@ bool GVN::processLoad(LoadInst *L, DenseMap<Value*, LoadInst*> &lastLoad,
|
|||||||
|
|
||||||
/// processInstruction - When calculating availability, handle an instruction
|
/// processInstruction - When calculating availability, handle an instruction
|
||||||
/// by inserting it into the appropriate sets
|
/// by inserting it into the appropriate sets
|
||||||
bool GVN::processInstruction(Instruction *I, ValueNumberedSet &currAvail,
|
bool GVN::processInstruction(Instruction *I,
|
||||||
DenseMap<Value*, LoadInst*> &lastSeenLoad,
|
DenseMap<Value*, LoadInst*> &lastSeenLoad,
|
||||||
SmallVectorImpl<Instruction*> &toErase) {
|
SmallVectorImpl<Instruction*> &toErase) {
|
||||||
if (LoadInst* L = dyn_cast<LoadInst>(I))
|
if (LoadInst* L = dyn_cast<LoadInst>(I))
|
||||||
@ -1088,8 +1034,8 @@ bool GVN::processInstruction(Instruction *I, ValueNumberedSet &currAvail,
|
|||||||
toErase.push_back(p);
|
toErase.push_back(p);
|
||||||
}
|
}
|
||||||
// Perform value-number based elimination
|
// Perform value-number based elimination
|
||||||
} else if (currAvail.test(num)) {
|
} else if (BaseMap.begin(num) != BaseMap.end()) {
|
||||||
Value* repl = find_leader(currAvail, num);
|
Value* repl = *BaseMap.begin(num);
|
||||||
|
|
||||||
// Remove it!
|
// Remove it!
|
||||||
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
|
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
|
||||||
@ -1100,8 +1046,7 @@ bool GVN::processInstruction(Instruction *I, ValueNumberedSet &currAvail,
|
|||||||
toErase.push_back(I);
|
toErase.push_back(I);
|
||||||
return true;
|
return true;
|
||||||
} else if (!I->isTerminator()) {
|
} else if (!I->isTerminator()) {
|
||||||
currAvail.set(num);
|
BaseMap.insert(num, I);
|
||||||
currAvail.insert(I);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -1127,72 +1072,57 @@ bool GVN::runOnFunction(Function& F) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GVN::processBlock(DomTreeNode* DTN) {
|
||||||
|
BasicBlock* BB = DTN->getBlock();
|
||||||
|
ValueNumberScope NewScope(BaseMap);
|
||||||
|
|
||||||
|
SmallVector<Instruction*, 8> toErase;
|
||||||
|
DenseMap<Value*, LoadInst*> lastSeenLoad;
|
||||||
|
bool changed_function = false;
|
||||||
|
|
||||||
|
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
|
||||||
|
BI != BE;) {
|
||||||
|
changed_function |= processInstruction(BI, lastSeenLoad, toErase);
|
||||||
|
if (toErase.empty()) {
|
||||||
|
++BI;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we need some instructions deleted, do it now.
|
||||||
|
NumGVNInstr += toErase.size();
|
||||||
|
|
||||||
|
// Avoid iterator invalidation.
|
||||||
|
bool AtStart = BI == BB->begin();
|
||||||
|
if (!AtStart)
|
||||||
|
--BI;
|
||||||
|
|
||||||
|
for (SmallVector<Instruction*, 4>::iterator I = toErase.begin(),
|
||||||
|
E = toErase.end(); I != E; ++I)
|
||||||
|
(*I)->eraseFromParent();
|
||||||
|
|
||||||
|
if (AtStart)
|
||||||
|
BI = BB->begin();
|
||||||
|
else
|
||||||
|
++BI;
|
||||||
|
|
||||||
|
toErase.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); I != E; ++I)
|
||||||
|
changed_function |= processBlock(*I);
|
||||||
|
|
||||||
|
return changed_function;
|
||||||
|
}
|
||||||
|
|
||||||
// GVN::iterateOnFunction - Executes one iteration of GVN
|
// GVN::iterateOnFunction - Executes one iteration of GVN
|
||||||
bool GVN::iterateOnFunction(Function &F) {
|
bool GVN::iterateOnFunction(Function &F) {
|
||||||
// Clean out global sets from any previous functions
|
// Clean out global sets from any previous functions
|
||||||
VN.clear();
|
VN.clear();
|
||||||
availableOut.clear();
|
availableOut.clear();
|
||||||
phiMap.clear();
|
phiMap.clear();
|
||||||
|
|
||||||
bool changed_function = false;
|
|
||||||
|
|
||||||
DominatorTree &DT = getAnalysis<DominatorTree>();
|
DominatorTree &DT = getAnalysis<DominatorTree>();
|
||||||
|
|
||||||
SmallVector<Instruction*, 8> toErase;
|
|
||||||
DenseMap<Value*, LoadInst*> lastSeenLoad;
|
|
||||||
DenseMap<DomTreeNode*, size_t> numChildrenVisited;
|
|
||||||
|
|
||||||
// Top-down walk of the dominator tree
|
// Top-down walk of the dominator tree
|
||||||
for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()),
|
return processBlock(DT.getRootNode());
|
||||||
E = df_end(DT.getRootNode()); DI != E; ++DI) {
|
|
||||||
|
|
||||||
// Get the set to update for this block
|
|
||||||
ValueNumberedSet& currAvail = availableOut[DI->getBlock()];
|
|
||||||
lastSeenLoad.clear();
|
|
||||||
|
|
||||||
BasicBlock* BB = DI->getBlock();
|
|
||||||
|
|
||||||
// A block inherits AVAIL_OUT from its dominator
|
|
||||||
if (DI->getIDom() != 0) {
|
|
||||||
currAvail = availableOut[DI->getIDom()->getBlock()];
|
|
||||||
|
|
||||||
numChildrenVisited[DI->getIDom()]++;
|
|
||||||
|
|
||||||
if (numChildrenVisited[DI->getIDom()] == DI->getIDom()->getNumChildren()) {
|
|
||||||
availableOut.erase(DI->getIDom()->getBlock());
|
|
||||||
numChildrenVisited.erase(DI->getIDom());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
|
|
||||||
BI != BE;) {
|
|
||||||
changed_function |= processInstruction(BI, currAvail,
|
|
||||||
lastSeenLoad, toErase);
|
|
||||||
if (toErase.empty()) {
|
|
||||||
++BI;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we need some instructions deleted, do it now.
|
|
||||||
NumGVNInstr += toErase.size();
|
|
||||||
|
|
||||||
// Avoid iterator invalidation.
|
|
||||||
bool AtStart = BI == BB->begin();
|
|
||||||
if (!AtStart)
|
|
||||||
--BI;
|
|
||||||
|
|
||||||
for (SmallVector<Instruction*, 4>::iterator I = toErase.begin(),
|
|
||||||
E = toErase.end(); I != E; ++I)
|
|
||||||
(*I)->eraseFromParent();
|
|
||||||
|
|
||||||
if (AtStart)
|
|
||||||
BI = BB->begin();
|
|
||||||
else
|
|
||||||
++BI;
|
|
||||||
|
|
||||||
toErase.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return changed_function;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user