aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/StrongPHIElimination.cpp
diff options
context:
space:
mode:
authorCameron Zwarich <zwarich@apple.com>2010-12-29 11:00:09 +0000
committerCameron Zwarich <zwarich@apple.com>2010-12-29 11:00:09 +0000
commit1558f5ed1975495c0394d9de7acc144d0c8742da (patch)
treeb21e4210aabcd879ce9c93a6675494221b401ec8 /lib/CodeGen/StrongPHIElimination.cpp
parent12db7b68b683371a6ae464e76b4c850fa0199eeb (diff)
Instead of processing every instruction when splitting interferences, only
process those instructions that define phi sources. This is a 47% speedup of StrongPHIElimination compile time on 403.gcc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122627 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/StrongPHIElimination.cpp')
-rw-r--r--lib/CodeGen/StrongPHIElimination.cpp88
1 files changed, 61 insertions, 27 deletions
diff --git a/lib/CodeGen/StrongPHIElimination.cpp b/lib/CodeGen/StrongPHIElimination.cpp
index 4749d8eca8..87bb803488 100644
--- a/lib/CodeGen/StrongPHIElimination.cpp
+++ b/lib/CodeGen/StrongPHIElimination.cpp
@@ -107,8 +107,6 @@ namespace {
/// Isolate a PHI.
void isolatePHI(MachineInstr*);
- void PartitionRegisters(MachineFunction& MF);
-
/// Traverses a basic block, splitting any interferences found between
/// registers in the same congruence class. It takes two DenseMaps as
/// arguments that it also updates: CurrentDominatingParent, which maps
@@ -142,6 +140,10 @@ namespace {
DenseMap<unsigned, Node*> RegNodeMap;
+ // Maps a basic block to a list of its defs of registers that appear as PHI
+ // sources.
+ DenseMap<MachineBasicBlock*, std::vector<MachineInstr*> > PHISrcDefs;
+
// FIXME: Can these two data structures be combined? Would a std::multimap
// be any better?
@@ -161,6 +163,16 @@ namespace {
typedef DenseMap<unsigned, MachineInstr*> DestCopyMap;
DestCopyMap InsertedDestCopies;
};
+
+ struct MIIndexCompare {
+ MIIndexCompare(LiveIntervals* LiveIntervals) : LI(LiveIntervals) { }
+
+ bool operator()(const MachineInstr* LHS, const MachineInstr* RHS) const {
+ return LI->getInstructionIndex(LHS) < LI->getInstructionIndex(RHS);
+ }
+
+ LiveIntervals* LI;
+ };
} // namespace
char StrongPHIElimination::ID = 0;
@@ -207,7 +219,27 @@ bool StrongPHIElimination::runOnMachineFunction(MachineFunction& MF) {
DT = &getAnalysis<MachineDominatorTree>();
LI = &getAnalysis<LiveIntervals>();
- PartitionRegisters(MF);
+ for (MachineFunction::iterator I = MF.begin(), E = MF.end();
+ I != E; ++I) {
+ for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end();
+ BBI != BBE && BBI->isPHI(); ++BBI) {
+ unsigned DestReg = BBI->getOperand(0).getReg();
+ addReg(DestReg);
+ PHISrcDefs[I].push_back(BBI);
+
+ for (unsigned i = 1; i < BBI->getNumOperands(); i += 2) {
+ MachineOperand& SrcMO = BBI->getOperand(i);
+ unsigned SrcReg = SrcMO.getReg();
+ addReg(SrcReg);
+ unionRegs(DestReg, SrcReg);
+
+ for (MachineRegisterInfo::def_iterator DI = MRI->def_begin(SrcReg),
+ DE = MRI->def_end(); DI != DE; ++DI) {
+ PHISrcDefs[DI->getParent()].push_back(&*DI);
+ }
+ }
+ }
+ }
// Perform a depth-first traversal of the dominator tree, splitting
// interferences amongst PHI-congruence classes.
@@ -232,7 +264,20 @@ bool StrongPHIElimination::runOnMachineFunction(MachineFunction& MF) {
// FIXME: Preserve the equivalence classes during copy insertion and use
// the preversed equivalence classes instead of recomputing them.
RegNodeMap.clear();
- PartitionRegisters(MF);
+ for (MachineFunction::iterator I = MF.begin(), E = MF.end();
+ I != E; ++I) {
+ for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end();
+ BBI != BBE && BBI->isPHI(); ++BBI) {
+ unsigned DestReg = BBI->getOperand(0).getReg();
+ addReg(DestReg);
+
+ for (unsigned i = 1; i < BBI->getNumOperands(); i += 2) {
+ unsigned SrcReg = BBI->getOperand(i).getReg();
+ addReg(SrcReg);
+ unionRegs(DestReg, SrcReg);
+ }
+ }
+ }
DenseMap<unsigned, unsigned> RegRenamingMap;
bool Changed = false;
@@ -336,6 +381,7 @@ bool StrongPHIElimination::runOnMachineFunction(MachineFunction& MF) {
Allocator.Reset();
RegNodeMap.clear();
+ PHISrcDefs.clear();
InsertedSrcCopySet.clear();
InsertedSrcCopyMap.clear();
InsertedDestCopies.clear();
@@ -410,23 +456,6 @@ void StrongPHIElimination::isolatePHI(MachineInstr* PHI) {
Node->parent.setInt(Node->parent.getInt() | Node::kPHIIsolatedFlag);
}
-void StrongPHIElimination::PartitionRegisters(MachineFunction& MF) {
- for (MachineFunction::iterator I = MF.begin(), E = MF.end();
- I != E; ++I) {
- for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end();
- BBI != BBE && BBI->isPHI(); ++BBI) {
- unsigned DestReg = BBI->getOperand(0).getReg();
- addReg(DestReg);
-
- for (unsigned i = 1; i < BBI->getNumOperands(); i += 2) {
- unsigned SrcReg = BBI->getOperand(i).getReg();
- addReg(SrcReg);
- unionRegs(DestReg, SrcReg);
- }
- }
- }
-}
-
/// SplitInterferencesForBasicBlock - traverses a basic block, splitting any
/// interferences found between registers in the same congruence class. It
/// takes two DenseMaps as arguments that it also updates:
@@ -471,10 +500,15 @@ StrongPHIElimination::SplitInterferencesForBasicBlock(
MachineBasicBlock& MBB,
DenseMap<unsigned, unsigned>& CurrentDominatingParent,
DenseMap<unsigned, unsigned>& ImmediateDominatingParent) {
- for (MachineBasicBlock::iterator BBI = MBB.begin(), BBE = MBB.end();
- BBI != BBE; ++BBI) {
- for (MachineInstr::const_mop_iterator I = BBI->operands_begin(),
- E = BBI->operands_end(); I != E; ++I) {
+ // Sort defs by their order in the original basic block, as the code below
+ // assumes that it is processing definitions in dominance order.
+ std::vector<MachineInstr*>& DefInstrs = PHISrcDefs[&MBB];
+ std::sort(DefInstrs.begin(), DefInstrs.end(), MIIndexCompare(LI));
+
+ for (std::vector<MachineInstr*>::const_iterator BBI = DefInstrs.begin(),
+ BBE = DefInstrs.end(); BBI != BBE; ++BBI) {
+ for (MachineInstr::const_mop_iterator I = (*BBI)->operands_begin(),
+ E = (*BBI)->operands_end(); I != E; ++I) {
const MachineOperand& MO = *I;
// FIXME: This would be faster if it were possible to bail out of checking
@@ -506,7 +540,7 @@ StrongPHIElimination::SplitInterferencesForBasicBlock(
// Pop registers from the stack represented by ImmediateDominatingParent
// until we find a parent that dominates the current instruction.
- while (NewParent && (!DT->dominates(MRI->getVRegDef(NewParent), BBI)
+ while (NewParent && (!DT->dominates(MRI->getVRegDef(NewParent), *BBI)
|| !getRegColor(NewParent)))
NewParent = ImmediateDominatingParent[NewParent];
@@ -514,7 +548,7 @@ StrongPHIElimination::SplitInterferencesForBasicBlock(
// instruction, so it is only necessary to check for the liveness of
// NewParent in order to check for an interference.
if (NewParent
- && LI->getInterval(NewParent).liveAt(LI->getInstructionIndex(BBI))) {
+ && LI->getInterval(NewParent).liveAt(LI->getInstructionIndex(*BBI))) {
// If there is an interference, always isolate the new register. This
// could be improved by using a heuristic that decides which of the two
// registers to isolate.