mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 16:33:28 +00:00
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:
parent
9b00685bb6
commit
835810bbf8
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user