Add support for slow-path GVN with full phi construction for scalars. This is disabled for now, as it actually pessimizes code in the abscence

of phi translation for load elimination.  This slow down GVN a bit, by about 2% on 403.gcc.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61021 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Owen Anderson 2008-12-15 02:03:00 +00:00
parent 67e3566d8f
commit 255dafc5de

View File

@ -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/PostOrderIterator.h"
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
@ -727,7 +728,7 @@ namespace {
SmallVectorImpl<Instruction*> &toErase); SmallVectorImpl<Instruction*> &toErase);
bool processNonLocalLoad(LoadInst* L, bool processNonLocalLoad(LoadInst* L,
SmallVectorImpl<Instruction*> &toErase); SmallVectorImpl<Instruction*> &toErase);
bool processBlock(DomTreeNode* DTN); bool processBlock(BasicBlock* BB);
Value *GetValueForBlock(BasicBlock *BB, Instruction* orig, Value *GetValueForBlock(BasicBlock *BB, Instruction* orig,
DenseMap<BasicBlock*, Value*> &Phis, DenseMap<BasicBlock*, Value*> &Phis,
bool top_level = false); bool top_level = false);
@ -738,6 +739,7 @@ namespace {
bool performPRE(Function& F); bool performPRE(Function& F);
Value* lookupNumber(BasicBlock* BB, uint32_t num); Value* lookupNumber(BasicBlock* BB, uint32_t num);
bool mergeBlockIntoPredecessor(BasicBlock* BB); bool mergeBlockIntoPredecessor(BasicBlock* BB);
Value* AttemptRedundancyElimination(Instruction* orig, unsigned valno);
void cleanupGlobalSets(); void cleanupGlobalSets();
}; };
@ -1222,6 +1224,60 @@ Value* GVN::lookupNumber(BasicBlock* BB, uint32_t num) {
return 0; return 0;
} }
/// AttemptRedundancyElimination - If the "fast path" of redundancy elimination
/// by inheritance from the dominator fails, see if we can perform phi
/// construction to eliminate the redundancy.
Value* GVN::AttemptRedundancyElimination(Instruction* orig, unsigned valno) {
BasicBlock* BaseBlock = orig->getParent();
SmallPtrSet<BasicBlock*, 4> Visited;
SmallVector<BasicBlock*, 8> Stack;
Stack.push_back(BaseBlock);
DenseMap<BasicBlock*, Value*> Results;
// Walk backwards through our predecessors, looking for instances of the
// value number we're looking for. Instances are recorded in the Results
// map, which is then used to perform phi construction.
while (!Stack.empty()) {
BasicBlock* Current = Stack.back();
Stack.pop_back();
// If we've walked all the way to a proper dominator, then give up. Cases
// where the instance is in the dominator will have been caught by the fast
// path, and any cases that require phi construction further than this are
// probably not worth it anyways. Note that this is a SIGNIFICANT compile
// time improvement.
if (DT->properlyDominates(Current, orig->getParent())) return 0;
DenseMap<BasicBlock*, ValueNumberScope*>::iterator LA =
localAvail.find(Current);
if (LA == localAvail.end()) return 0;
DenseMap<unsigned, Value*>::iterator V = LA->second->table.find(valno);
if (V != LA->second->table.end()) {
// Found an instance, record it.
Results.insert(std::make_pair(Current, V->second));
continue;
}
// If we reach the beginning of the function, then give up.
if (pred_begin(Current) == pred_end(Current))
return 0;
for (pred_iterator PI = pred_begin(Current), PE = pred_end(Current);
PI != PE; ++PI)
if (Visited.insert(*PI))
Stack.push_back(*PI);
}
// If we didn't find instances, give up. Otherwise, perform phi construction.
if (Results.size() == 0)
return 0;
else
return GetValueForBlock(BaseBlock, orig, Results, true);
}
/// 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, bool GVN::processInstruction(Instruction *I,
@ -1270,7 +1326,8 @@ bool GVN::processInstruction(Instruction *I,
} else if (num == nextNum) { } else if (num == nextNum) {
localAvail[I->getParent()]->table.insert(std::make_pair(num, I)); localAvail[I->getParent()]->table.insert(std::make_pair(num, I));
// Perform value-number based elimination // Perform fast-path value-number based elimination of values inherited from
// dominators.
} else if (Value* repl = lookupNumber(I->getParent(), num)) { } else if (Value* repl = lookupNumber(I->getParent(), num)) {
// Remove it! // Remove it!
VN.erase(I); VN.erase(I);
@ -1279,6 +1336,18 @@ bool GVN::processInstruction(Instruction *I,
MD->invalidateCachedPointerInfo(repl); MD->invalidateCachedPointerInfo(repl);
toErase.push_back(I); toErase.push_back(I);
return true; return true;
#if 0
// Perform slow-pathvalue-number based elimination with phi construction.
} else if (Value* repl = AttemptRedundancyElimination(I, num)) {
// Remove it!
VN.erase(I);
I->replaceAllUsesWith(repl);
if (isa<PointerType>(repl->getType()))
MD->invalidateCachedPointerInfo(repl);
toErase.push_back(I);
return true;
#endif
} else { } else {
localAvail[I->getParent()]->table.insert(std::make_pair(num, I)); localAvail[I->getParent()]->table.insert(std::make_pair(num, I));
} }
@ -1337,8 +1406,8 @@ bool GVN::runOnFunction(Function& F) {
} }
bool GVN::processBlock(DomTreeNode* DTN) { bool GVN::processBlock(BasicBlock* BB) {
BasicBlock* BB = DTN->getBlock(); DomTreeNode* DTN = DT->getNode(BB);
// FIXME: Kill off toErase by doing erasing eagerly in a helper function (and // FIXME: Kill off toErase by doing erasing eagerly in a helper function (and
// incrementing BI before processing an instruction). // incrementing BI before processing an instruction).
SmallVector<Instruction*, 8> toErase; SmallVector<Instruction*, 8> toErase;
@ -1538,9 +1607,10 @@ bool GVN::iterateOnFunction(Function &F) {
// Top-down walk of the dominator tree // Top-down walk of the dominator tree
bool changed = false; bool changed = false;
for (df_iterator<DomTreeNode*> DI = df_begin(DT->getRootNode()), ReversePostOrderTraversal<Function*> RPOT(&F);
DE = df_end(DT->getRootNode()); DI != DE; ++DI) for (ReversePostOrderTraversal<Function*>::rpo_iterator RI = RPOT.begin(),
changed |= processBlock(*DI); RE = RPOT.end(); RI != RE; ++RI)
changed |= processBlock(*RI);
return changed; return changed;
} }