forked from OSchip/llvm-project
parent
0555f7eefa
commit
4eab008b5a
|
@ -17,6 +17,8 @@
|
|||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/ADT/ScopedHashTable.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
@ -41,6 +43,8 @@ namespace llvm {
|
|||
switch (MO.getType()) {
|
||||
default: break;
|
||||
case MachineOperand::MO_Register:
|
||||
if (MO.isDef() && TargetRegisterInfo::isVirtualRegister(MO.getReg()))
|
||||
continue; // Skip virtual register defs.
|
||||
Key |= MO.getReg();
|
||||
break;
|
||||
case MachineOperand::MO_Immediate:
|
||||
|
@ -76,18 +80,24 @@ namespace llvm {
|
|||
|
||||
static bool isEqual(const MachineInstr* const &LHS,
|
||||
const MachineInstr* const &RHS) {
|
||||
return LHS->isIdenticalTo(RHS);
|
||||
if (RHS == getEmptyKey() || RHS == getTombstoneKey() ||
|
||||
LHS == getEmptyKey() || LHS == getTombstoneKey())
|
||||
return LHS == RHS;
|
||||
return LHS->isIdenticalTo(RHS, MachineInstr::IgnoreVRegDefs);
|
||||
}
|
||||
};
|
||||
} // end llvm namespace
|
||||
|
||||
namespace {
|
||||
class MachineCSE : public MachineFunctionPass {
|
||||
ScopedHashTable<MachineInstr*, unsigned> VNT;
|
||||
const TargetInstrInfo *TII;
|
||||
MachineRegisterInfo *MRI;
|
||||
MachineDominatorTree *DT;
|
||||
ScopedHashTable<MachineInstr*, unsigned> VNT;
|
||||
unsigned CurrVN;
|
||||
public:
|
||||
static char ID; // Pass identification
|
||||
MachineCSE() : MachineFunctionPass(&ID) {}
|
||||
MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {}
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF);
|
||||
|
||||
|
@ -99,6 +109,7 @@ namespace {
|
|||
}
|
||||
|
||||
private:
|
||||
bool PerformTrivialCoalescing(MachineInstr *MI, MachineBasicBlock *MBB);
|
||||
bool ProcessBlock(MachineDomTreeNode *Node);
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
@ -109,16 +120,89 @@ X("machine-cse", "Machine Common Subexpression Elimination");
|
|||
|
||||
FunctionPass *llvm::createMachineCSEPass() { return new MachineCSE(); }
|
||||
|
||||
bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
|
||||
ScopedHashTableScope<MachineInstr*, unsigned> VNTS(VNT);
|
||||
MachineBasicBlock *MBB = Node->getBlock();
|
||||
for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;
|
||||
++I) {
|
||||
bool MachineCSE::PerformTrivialCoalescing(MachineInstr *MI,
|
||||
MachineBasicBlock *MBB) {
|
||||
bool Changed = false;
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
MachineOperand &MO = MI->getOperand(i);
|
||||
if (MO.isReg() && MO.isUse()) {
|
||||
unsigned Reg = MO.getReg();
|
||||
if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg))
|
||||
continue;
|
||||
MachineInstr *DefMI = MRI->getVRegDef(Reg);
|
||||
if (DefMI->getParent() == MBB) {
|
||||
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
|
||||
if (TII->isMoveInstr(*DefMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) &&
|
||||
TargetRegisterInfo::isVirtualRegister(SrcReg) &&
|
||||
!SrcSubIdx && !DstSubIdx) {
|
||||
MO.setReg(SrcReg);
|
||||
Changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
static bool hasLivePhysRegDefUse(MachineInstr *MI) {
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
MachineOperand &MO = MI->getOperand(i);
|
||||
if (!MO.isReg())
|
||||
continue;
|
||||
unsigned Reg = MO.getReg();
|
||||
if (!Reg)
|
||||
continue;
|
||||
if (TargetRegisterInfo::isPhysicalRegister(Reg) &&
|
||||
!(MO.isDef() && MO.isDead()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
|
||||
bool Changed = false;
|
||||
|
||||
ScopedHashTableScope<MachineInstr*, unsigned> VNTS(VNT);
|
||||
MachineBasicBlock *MBB = Node->getBlock();
|
||||
for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;
|
||||
++I) {
|
||||
MachineInstr *MI = &*I;
|
||||
bool SawStore = false;
|
||||
if (!MI->isSafeToMove(TII, 0, SawStore))
|
||||
continue;
|
||||
// Ignore copies or instructions that read / write physical registers
|
||||
// (except for dead defs of physical registers).
|
||||
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
|
||||
if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx))
|
||||
continue;
|
||||
if (hasLivePhysRegDefUse(MI))
|
||||
continue;
|
||||
|
||||
bool FoundCSE = VNT.count(MI);
|
||||
if (!FoundCSE) {
|
||||
// Look for trivial copy coalescing opportunities.
|
||||
if (PerformTrivialCoalescing(MI, MBB))
|
||||
FoundCSE = VNT.count(MI);
|
||||
}
|
||||
|
||||
if (FoundCSE)
|
||||
DEBUG(dbgs() << "Found a common subexpression: " << *MI);
|
||||
else
|
||||
VNT.insert(MI, ++CurrVN);
|
||||
}
|
||||
|
||||
// Recursively call ProcessBlock with childred.
|
||||
const std::vector<MachineDomTreeNode*> &Children = Node->getChildren();
|
||||
for (unsigned i = 0, e = Children.size(); i != e; ++i)
|
||||
Changed |= ProcessBlock(Children[i]);
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
bool MachineCSE::runOnMachineFunction(MachineFunction &MF) {
|
||||
TII = MF.getTarget().getInstrInfo();
|
||||
MRI = &MF.getRegInfo();
|
||||
DT = &getAnalysis<MachineDominatorTree>();
|
||||
return ProcessBlock(DT->getRootNode());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue