Allow machine cse to cse instructions which define physical registers. Controlled by option -machine-cse-phys-defs.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@104385 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2010-05-21 21:22:19 +00:00
parent 9b00685bb6
commit 835810bbf8

View File

@ -23,6 +23,7 @@
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ScopedHashTable.h" #include "llvm/ADT/ScopedHashTable.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
using namespace llvm; using namespace llvm;
@ -30,6 +31,9 @@ using namespace llvm;
STATISTIC(NumCoalesces, "Number of copies coalesced"); STATISTIC(NumCoalesces, "Number of copies coalesced");
STATISTIC(NumCSEs, "Number of common subexpression eliminated"); STATISTIC(NumCSEs, "Number of common subexpression eliminated");
static cl::opt<bool> CSEPhysDef("machine-cse-phys-defs",
cl::init(false), cl::Hidden);
namespace { namespace {
class MachineCSE : public MachineFunctionPass { class MachineCSE : public MachineFunctionPass {
const TargetInstrInfo *TII; const TargetInstrInfo *TII;
@ -39,7 +43,7 @@ namespace {
MachineRegisterInfo *MRI; MachineRegisterInfo *MRI;
public: public:
static char ID; // Pass identification static char ID; // Pass identification
MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {} MachineCSE() : MachineFunctionPass(&ID), LookAheadLimit(5), CurrVN(0) {}
virtual bool runOnMachineFunction(MachineFunction &MF); virtual bool runOnMachineFunction(MachineFunction &MF);
@ -52,6 +56,7 @@ namespace {
} }
private: private:
const unsigned LookAheadLimit;
typedef ScopedHashTableScope<MachineInstr*, unsigned, typedef ScopedHashTableScope<MachineInstr*, unsigned,
MachineInstrExpressionTrait> ScopeType; MachineInstrExpressionTrait> ScopeType;
DenseMap<MachineBasicBlock*, ScopeType*> ScopeMap; DenseMap<MachineBasicBlock*, ScopeType*> ScopeMap;
@ -62,8 +67,12 @@ namespace {
bool PerformTrivialCoalescing(MachineInstr *MI, MachineBasicBlock *MBB); bool PerformTrivialCoalescing(MachineInstr *MI, MachineBasicBlock *MBB);
bool isPhysDefTriviallyDead(unsigned Reg, bool isPhysDefTriviallyDead(unsigned Reg,
MachineBasicBlock::const_iterator I, MachineBasicBlock::const_iterator I,
MachineBasicBlock::const_iterator E); MachineBasicBlock::const_iterator E) const ;
bool hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB); bool hasLivePhysRegDefUse(const MachineInstr *MI,
const MachineBasicBlock *MBB,
unsigned &PhysDef) const;
bool PhysRegDefReaches(MachineInstr *CSMI, MachineInstr *MI,
unsigned PhysDef) const;
bool isCSECandidate(MachineInstr *MI); bool isCSECandidate(MachineInstr *MI);
bool isProfitableToCSE(unsigned CSReg, unsigned Reg, bool isProfitableToCSE(unsigned CSReg, unsigned Reg,
MachineInstr *CSMI, MachineInstr *MI); MachineInstr *CSMI, MachineInstr *MI);
@ -124,10 +133,11 @@ bool MachineCSE::PerformTrivialCoalescing(MachineInstr *MI,
return Changed; return Changed;
} }
bool MachineCSE::isPhysDefTriviallyDead(unsigned Reg, bool
MachineBasicBlock::const_iterator I, MachineCSE::isPhysDefTriviallyDead(unsigned Reg,
MachineBasicBlock::const_iterator E) { MachineBasicBlock::const_iterator I,
unsigned LookAheadLeft = 5; MachineBasicBlock::const_iterator E) const {
unsigned LookAheadLeft = LookAheadLeft;
while (LookAheadLeft) { while (LookAheadLeft) {
// Skip over dbg_value's. // Skip over dbg_value's.
while (I != E && I->isDebugValue()) while (I != E && I->isDebugValue())
@ -145,6 +155,7 @@ bool MachineCSE::isPhysDefTriviallyDead(unsigned Reg,
if (!TRI->regsOverlap(MO.getReg(), Reg)) if (!TRI->regsOverlap(MO.getReg(), Reg))
continue; continue;
if (MO.isUse()) if (MO.isUse())
// Found a use!
return false; return false;
SeenDef = true; SeenDef = true;
} }
@ -160,41 +171,73 @@ bool MachineCSE::isPhysDefTriviallyDead(unsigned Reg,
} }
/// hasLivePhysRegDefUse - Return true if the specified instruction read / write /// hasLivePhysRegDefUse - Return true if the specified instruction read / write
/// physical registers (except for dead defs of physical registers). /// physical registers (except for dead defs of physical registers). It also
bool MachineCSE::hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB){ /// returns the physical register def by reference if it's the only one.
unsigned PhysDef = 0; bool MachineCSE::hasLivePhysRegDefUse(const MachineInstr *MI,
const MachineBasicBlock *MBB,
unsigned &PhysDef) const {
PhysDef = 0;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(i); const MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg()) if (!MO.isReg())
continue; continue;
unsigned Reg = MO.getReg(); unsigned Reg = MO.getReg();
if (!Reg) if (!Reg)
continue; continue;
if (TargetRegisterInfo::isPhysicalRegister(Reg)) { if (TargetRegisterInfo::isVirtualRegister(Reg))
if (MO.isUse()) continue;
// Can't touch anything to read a physical register. if (MO.isUse())
return true; // Can't touch anything to read a physical register.
if (MO.isDead()) return true;
// If the def is dead, it's ok. if (MO.isDead())
continue; // If the def is dead, it's ok.
// Ok, this is a physical register def that's not marked "dead". That's continue;
// common since this pass is run before livevariables. We can scan // Ok, this is a physical register def that's not marked "dead". That's
// forward a few instructions and check if it is obviously dead. // common since this pass is run before livevariables. We can scan
if (PhysDef) // forward a few instructions and check if it is obviously dead.
// Multiple physical register defs. These are rare, forget about it. if (PhysDef) {
return true; // Multiple physical register defs. These are rare, forget about it.
PhysDef = Reg; PhysDef = 0;
return true;
} }
PhysDef = Reg;
} }
if (PhysDef) { if (PhysDef) {
MachineBasicBlock::iterator I = MI; I = llvm::next(I); MachineBasicBlock::const_iterator I = MI; I = llvm::next(I);
if (!isPhysDefTriviallyDead(PhysDef, I, MBB->end())) if (!isPhysDefTriviallyDead(PhysDef, I, MBB->end()))
return true; return true;
} }
return false; return false;
} }
bool MachineCSE::PhysRegDefReaches(MachineInstr *CSMI, MachineInstr *MI,
unsigned PhysDef) const {
// For now conservatively returns false if the common subexpression is
// not in the same basic block as the given instruction.
MachineBasicBlock *MBB = MI->getParent();
if (CSMI->getParent() != MBB)
return false;
MachineBasicBlock::const_iterator I = CSMI; I = llvm::next(I);
MachineBasicBlock::const_iterator E = MI;
unsigned LookAheadLeft = LookAheadLimit;
while (LookAheadLeft) {
// Skip over dbg_value's.
while (I != E && I->isDebugValue())
++I;
if (I == E)
return true;
if (I->modifiesRegister(PhysDef, TRI))
return false;
--LookAheadLeft;
++I;
}
return false;
}
static bool isCopy(const MachineInstr *MI, const TargetInstrInfo *TII) { static bool isCopy(const MachineInstr *MI, const TargetInstrInfo *TII) {
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
return TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) || return TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) ||
@ -327,9 +370,20 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) {
// If the instruction defines a physical register and the value *may* be // If the instruction defines a physical register and the value *may* be
// used, then it's not safe to replace it with a common subexpression. // used, then it's not safe to replace it with a common subexpression.
if (FoundCSE && hasLivePhysRegDefUse(MI, MBB)) unsigned PhysDef = 0;
if (FoundCSE && hasLivePhysRegDefUse(MI, MBB, PhysDef)) {
FoundCSE = false; FoundCSE = false;
// ... Unless the CS is local and it also defines the physical register
// which is not clobbered in between.
if (PhysDef && CSEPhysDef) {
unsigned CSVN = VNT.lookup(MI);
MachineInstr *CSMI = Exps[CSVN];
if (PhysRegDefReaches(CSMI, MI, PhysDef))
FoundCSE = true;
}
}
if (!FoundCSE) { if (!FoundCSE) {
VNT.insert(MI, CurrVN++); VNT.insert(MI, CurrVN++);
Exps.push_back(MI); Exps.push_back(MI);