mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-20 09:30:43 +00:00
Machine CSE work in progress. It's doing some CSE now. But implicit def of physical registers are getting in the way.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97664 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1423c70b8f
commit
16b48b8a05
@ -25,6 +25,9 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
STATISTIC(NumCoalesces, "Number of copies coalesced");
|
||||||
|
STATISTIC(NumCSEs, "Number of common subexpression eliminated");
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
template<> struct DenseMapInfo<MachineInstr*> {
|
template<> struct DenseMapInfo<MachineInstr*> {
|
||||||
static inline MachineInstr *getEmptyKey() {
|
static inline MachineInstr *getEmptyKey() {
|
||||||
@ -93,8 +96,6 @@ namespace {
|
|||||||
const TargetInstrInfo *TII;
|
const TargetInstrInfo *TII;
|
||||||
MachineRegisterInfo *MRI;
|
MachineRegisterInfo *MRI;
|
||||||
MachineDominatorTree *DT;
|
MachineDominatorTree *DT;
|
||||||
ScopedHashTable<MachineInstr*, unsigned> VNT;
|
|
||||||
unsigned CurrVN;
|
|
||||||
public:
|
public:
|
||||||
static char ID; // Pass identification
|
static char ID; // Pass identification
|
||||||
MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {}
|
MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {}
|
||||||
@ -109,6 +110,10 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
unsigned CurrVN;
|
||||||
|
ScopedHashTable<MachineInstr*, unsigned> VNT;
|
||||||
|
SmallVector<MachineInstr*, 64> Exps;
|
||||||
|
|
||||||
bool PerformTrivialCoalescing(MachineInstr *MI, MachineBasicBlock *MBB);
|
bool PerformTrivialCoalescing(MachineInstr *MI, MachineBasicBlock *MBB);
|
||||||
bool ProcessBlock(MachineDomTreeNode *Node);
|
bool ProcessBlock(MachineDomTreeNode *Node);
|
||||||
};
|
};
|
||||||
@ -125,22 +130,28 @@ bool MachineCSE::PerformTrivialCoalescing(MachineInstr *MI,
|
|||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
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);
|
MachineOperand &MO = MI->getOperand(i);
|
||||||
if (MO.isReg() && MO.isUse()) {
|
if (!MO.isReg() || !MO.isUse())
|
||||||
|
continue;
|
||||||
unsigned Reg = MO.getReg();
|
unsigned Reg = MO.getReg();
|
||||||
if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg))
|
if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg))
|
||||||
continue;
|
continue;
|
||||||
|
if (!MRI->hasOneUse(Reg))
|
||||||
|
// Only coalesce single use copies. This ensure the copy will be
|
||||||
|
// deleted.
|
||||||
|
continue;
|
||||||
MachineInstr *DefMI = MRI->getVRegDef(Reg);
|
MachineInstr *DefMI = MRI->getVRegDef(Reg);
|
||||||
if (DefMI->getParent() == MBB) {
|
if (DefMI->getParent() != MBB)
|
||||||
|
continue;
|
||||||
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
|
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
|
||||||
if (TII->isMoveInstr(*DefMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) &&
|
if (TII->isMoveInstr(*DefMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) &&
|
||||||
TargetRegisterInfo::isVirtualRegister(SrcReg) &&
|
TargetRegisterInfo::isVirtualRegister(SrcReg) &&
|
||||||
!SrcSubIdx && !DstSubIdx) {
|
!SrcSubIdx && !DstSubIdx) {
|
||||||
MO.setReg(SrcReg);
|
MO.setReg(SrcReg);
|
||||||
|
DefMI->eraseFromParent();
|
||||||
|
++NumCoalesces;
|
||||||
Changed = true;
|
Changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
@ -153,6 +164,8 @@ static bool hasLivePhysRegDefUse(MachineInstr *MI) {
|
|||||||
unsigned Reg = MO.getReg();
|
unsigned Reg = MO.getReg();
|
||||||
if (!Reg)
|
if (!Reg)
|
||||||
continue;
|
continue;
|
||||||
|
// FIXME: This is obviously overly conservative. On x86 lots of instructions
|
||||||
|
// will def EFLAGS and they are not marked dead at this point.
|
||||||
if (TargetRegisterInfo::isPhysicalRegister(Reg) &&
|
if (TargetRegisterInfo::isPhysicalRegister(Reg) &&
|
||||||
!(MO.isDef() && MO.isDead()))
|
!(MO.isDef() && MO.isDead()))
|
||||||
return true;
|
return true;
|
||||||
@ -165,16 +178,17 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
|
|||||||
|
|
||||||
ScopedHashTableScope<MachineInstr*, unsigned> VNTS(VNT);
|
ScopedHashTableScope<MachineInstr*, unsigned> VNTS(VNT);
|
||||||
MachineBasicBlock *MBB = Node->getBlock();
|
MachineBasicBlock *MBB = Node->getBlock();
|
||||||
for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;
|
for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ) {
|
||||||
++I) {
|
|
||||||
MachineInstr *MI = &*I;
|
MachineInstr *MI = &*I;
|
||||||
|
++I;
|
||||||
bool SawStore = false;
|
bool SawStore = false;
|
||||||
if (!MI->isSafeToMove(TII, 0, SawStore))
|
if (!MI->isSafeToMove(TII, 0, SawStore))
|
||||||
continue;
|
continue;
|
||||||
// Ignore copies or instructions that read / write physical registers
|
// Ignore copies or instructions that read / write physical registers
|
||||||
// (except for dead defs of physical registers).
|
// (except for dead defs of physical registers).
|
||||||
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
|
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
|
||||||
if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx))
|
if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) ||
|
||||||
|
MI->isExtractSubreg() || MI->isInsertSubreg() || MI->isSubregToReg())
|
||||||
continue;
|
continue;
|
||||||
if (hasLivePhysRegDefUse(MI))
|
if (hasLivePhysRegDefUse(MI))
|
||||||
continue;
|
continue;
|
||||||
@ -186,10 +200,33 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
|
|||||||
FoundCSE = VNT.count(MI);
|
FoundCSE = VNT.count(MI);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FoundCSE)
|
if (!FoundCSE) {
|
||||||
DEBUG(dbgs() << "Found a common subexpression: " << *MI);
|
VNT.insert(MI, CurrVN++);
|
||||||
else
|
Exps.push_back(MI);
|
||||||
VNT.insert(MI, ++CurrVN);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Found a common subexpression, eliminate it.
|
||||||
|
unsigned CSVN = VNT.lookup(MI);
|
||||||
|
MachineInstr *CSMI = Exps[CSVN];
|
||||||
|
DEBUG(dbgs() << "Examining: " << *MI);
|
||||||
|
DEBUG(dbgs() << "*** Found a common subexpression: " << *CSMI);
|
||||||
|
unsigned NumDefs = MI->getDesc().getNumDefs();
|
||||||
|
for (unsigned i = 0, e = MI->getNumOperands(); NumDefs && i != e; ++i) {
|
||||||
|
MachineOperand &MO = MI->getOperand(i);
|
||||||
|
if (!MO.isReg() || !MO.isDef())
|
||||||
|
continue;
|
||||||
|
unsigned OldReg = MO.getReg();
|
||||||
|
unsigned NewReg = CSMI->getOperand(i).getReg();
|
||||||
|
assert(OldReg != NewReg &&
|
||||||
|
TargetRegisterInfo::isVirtualRegister(OldReg) &&
|
||||||
|
TargetRegisterInfo::isVirtualRegister(NewReg) &&
|
||||||
|
"Do not CSE physical register defs!");
|
||||||
|
MRI->replaceRegWith(OldReg, NewReg);
|
||||||
|
--NumDefs;
|
||||||
|
}
|
||||||
|
MI->eraseFromParent();
|
||||||
|
++NumCSEs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively call ProcessBlock with childred.
|
// Recursively call ProcessBlock with childred.
|
||||||
|
Loading…
Reference in New Issue
Block a user