mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-19 04:32:19 +00:00
Avoid cse load instructions unless they are known to be invariant loads.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97747 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bbf39b0fd9
commit
a5f32cb3d3
@ -18,6 +18,7 @@
|
|||||||
#include "llvm/CodeGen/MachineDominators.h"
|
#include "llvm/CodeGen/MachineDominators.h"
|
||||||
#include "llvm/CodeGen/MachineInstr.h"
|
#include "llvm/CodeGen/MachineInstr.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
|
#include "llvm/Analysis/AliasAnalysis.h"
|
||||||
#include "llvm/Target/TargetInstrInfo.h"
|
#include "llvm/Target/TargetInstrInfo.h"
|
||||||
#include "llvm/ADT/ScopedHashTable.h"
|
#include "llvm/ADT/ScopedHashTable.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
@ -34,6 +35,7 @@ namespace {
|
|||||||
const TargetRegisterInfo *TRI;
|
const TargetRegisterInfo *TRI;
|
||||||
MachineRegisterInfo *MRI;
|
MachineRegisterInfo *MRI;
|
||||||
MachineDominatorTree *DT;
|
MachineDominatorTree *DT;
|
||||||
|
AliasAnalysis *AA;
|
||||||
public:
|
public:
|
||||||
static char ID; // Pass identification
|
static char ID; // Pass identification
|
||||||
MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {}
|
MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {}
|
||||||
@ -43,6 +45,7 @@ namespace {
|
|||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.setPreservesCFG();
|
AU.setPreservesCFG();
|
||||||
MachineFunctionPass::getAnalysisUsage(AU);
|
MachineFunctionPass::getAnalysisUsage(AU);
|
||||||
|
AU.addRequired<AliasAnalysis>();
|
||||||
AU.addRequired<MachineDominatorTree>();
|
AU.addRequired<MachineDominatorTree>();
|
||||||
AU.addPreserved<MachineDominatorTree>();
|
AU.addPreserved<MachineDominatorTree>();
|
||||||
}
|
}
|
||||||
@ -52,11 +55,12 @@ namespace {
|
|||||||
ScopedHashTable<MachineInstr*, unsigned, MachineInstrExpressionTrait> VNT;
|
ScopedHashTable<MachineInstr*, unsigned, MachineInstrExpressionTrait> VNT;
|
||||||
SmallVector<MachineInstr*, 64> Exps;
|
SmallVector<MachineInstr*, 64> Exps;
|
||||||
|
|
||||||
bool hasLivePhysRegDefUse(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);
|
||||||
bool PerformTrivialCoalescing(MachineInstr *MI, MachineBasicBlock *MBB);
|
bool hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB);
|
||||||
|
bool isCSECandidate(MachineInstr *MI);
|
||||||
bool ProcessBlock(MachineDomTreeNode *Node);
|
bool ProcessBlock(MachineDomTreeNode *Node);
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
@ -163,6 +167,33 @@ bool MachineCSE::hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MachineCSE::isCSECandidate(MachineInstr *MI) {
|
||||||
|
// 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) ||
|
||||||
|
MI->isExtractSubreg() || MI->isInsertSubreg() || MI->isSubregToReg())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Ignore stuff that we obviously can't move.
|
||||||
|
const TargetInstrDesc &TID = MI->getDesc();
|
||||||
|
if (TID.mayStore() || TID.isCall() || TID.isTerminator() ||
|
||||||
|
TID.hasUnmodeledSideEffects())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (TID.mayLoad()) {
|
||||||
|
// Okay, this instruction does a load. As a refinement, we allow the target
|
||||||
|
// to decide whether the loaded value is actually a constant. If so, we can
|
||||||
|
// actually use it as a load.
|
||||||
|
if (!MI->isInvariantLoad(AA))
|
||||||
|
// FIXME: we should be able to hoist loads with no other side effects if
|
||||||
|
// there are no other instructions which can change memory in this loop.
|
||||||
|
// This is a trivial form of alias analysis.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
|
bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
@ -172,14 +203,8 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
|
|||||||
for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ) {
|
for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ) {
|
||||||
MachineInstr *MI = &*I;
|
MachineInstr *MI = &*I;
|
||||||
++I;
|
++I;
|
||||||
bool SawStore = false;
|
|
||||||
if (!MI->isSafeToMove(TII, 0, SawStore))
|
if (!isCSECandidate(MI))
|
||||||
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) ||
|
|
||||||
MI->isExtractSubreg() || MI->isInsertSubreg() || MI->isSubregToReg())
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool FoundCSE = VNT.count(MI);
|
bool FoundCSE = VNT.count(MI);
|
||||||
@ -237,5 +262,6 @@ bool MachineCSE::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
TRI = MF.getTarget().getRegisterInfo();
|
TRI = MF.getTarget().getRegisterInfo();
|
||||||
MRI = &MF.getRegInfo();
|
MRI = &MF.getRegInfo();
|
||||||
DT = &getAnalysis<MachineDominatorTree>();
|
DT = &getAnalysis<MachineDominatorTree>();
|
||||||
|
AA = &getAnalysis<AliasAnalysis>();
|
||||||
return ProcessBlock(DT->getRootNode());
|
return ProcessBlock(DT->getRootNode());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user