Teach SimplifyCFG how to eliminate duplicate PHI nodes within a block.

This reduces codesize on a variety of codes by 1-2% on x86-64. It also
helps clean up after SSAUpdater.

llvm-svn: 85626
This commit is contained in:
Dan Gohman 2009-10-30 22:39:04 +00:00
parent 74eb5d71a3
commit 1a95106602
1 changed files with 61 additions and 0 deletions

View File

@ -24,6 +24,7 @@
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
@ -1748,6 +1749,63 @@ static bool SimplifyCondBranchToCondBranch(BranchInst *PBI, BranchInst *BI) {
return true; return true;
} }
/// EliminateDuplicatePHINodes - Check for and eliminate duplicate PHI
/// nodes in this block. This doesn't try to be clever about PHI nodes
/// which differ only in the order of the incoming values, but instcombine
/// orders them so it usually won't matter.
static bool EliminateDuplicatePHINodes(BasicBlock *BB) {
bool Changed = false;
// Map from PHI hash values to PHI nodes. If multiple PHIs have
// the same hash value, the element is the first PHI in the
// linked list in CollisionMap.
DenseMap<uintptr_t, PHINode *> HashMap;
// Maintain linked lists of PHI nodes with common hash values.
DenseMap<PHINode *, PHINode *> CollisionMap;
// Examine each PHI.
for (BasicBlock::iterator I = BB->begin();
PHINode *PN = dyn_cast<PHINode>(I++); ) {
// Compute a hash value on the operands. Instcombine will likely have sorted
// them, which helps expose duplicates, but we have to check all the
// operands to be safe in case instcombine hasn't run.
uintptr_t Hash = 0;
for (User::op_iterator I = PN->op_begin(), E = PN->op_end(); I != E; ++I) {
// This hash algorithm is quite weak as hash functions go, but it seems
// to do a good enough job for this particular purpose, and is very quick.
Hash ^= reinterpret_cast<uintptr_t>(static_cast<Value *>(*I));
Hash = (Hash << 7) | (Hash >> (sizeof(uintptr_t) * CHAR_BIT - 7));
}
// If we've never seen this hash value before, it's a unique PHI.
std::pair<DenseMap<uintptr_t, PHINode *>::iterator, bool> Pair =
HashMap.insert(std::make_pair(Hash, PN));
if (Pair.second) continue;
// Otherwise it's either a duplicate or a hash collision.
for (PHINode *OtherPN = Pair.first->second; ; ) {
if (OtherPN->isIdenticalTo(PN)) {
// A duplicate. Replace this PHI with its duplicate.
PN->replaceAllUsesWith(OtherPN);
PN->eraseFromParent();
Changed = true;
break;
}
// A non-duplicate hash collision.
DenseMap<PHINode *, PHINode *>::iterator I = CollisionMap.find(OtherPN);
if (I == CollisionMap.end()) {
// Set this PHI to be the head of the linked list of colliding PHIs.
PHINode *Old = Pair.first->second;
Pair.first->second = PN;
CollisionMap[PN] = Old;
break;
}
// Procede to the next PHI in the list.
OtherPN = I->second;
}
}
return Changed;
}
/// SimplifyCFG - This function is used to do simplification of a CFG. For /// SimplifyCFG - This function is used to do simplification of a CFG. For
/// example, it adjusts branches to branches to eliminate the extra hop, it /// example, it adjusts branches to branches to eliminate the extra hop, it
@ -1777,6 +1835,9 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
// away... // away...
Changed |= ConstantFoldTerminator(BB); Changed |= ConstantFoldTerminator(BB);
// Check for and eliminate duplicate PHI nodes in this block.
Changed |= EliminateDuplicatePHINodes(BB);
// If there is a trivial two-entry PHI node in this basic block, and we can // If there is a trivial two-entry PHI node in this basic block, and we can
// eliminate it, do so now. // eliminate it, do so now.
if (PHINode *PN = dyn_cast<PHINode>(BB->begin())) if (PHINode *PN = dyn_cast<PHINode>(BB->begin()))