mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-21 02:24:22 +00:00
[CodeGen] Teach the peephole optimizer to remember (and exploit) all folding
opportunities in the current basic block, rather than just the last one seen. <rdar://problem/16478629> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205481 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -133,7 +133,8 @@ namespace {
|
||||
bool foldImmediate(MachineInstr *MI, MachineBasicBlock *MBB,
|
||||
SmallSet<unsigned, 4> &ImmDefRegs,
|
||||
DenseMap<unsigned, MachineInstr*> &ImmDefMIs);
|
||||
bool isLoadFoldable(MachineInstr *MI, unsigned &FoldAsLoadDefReg);
|
||||
bool isLoadFoldable(MachineInstr *MI,
|
||||
SmallSet<unsigned, 16> &FoldAsLoadDefCandidates);
|
||||
};
|
||||
}
|
||||
|
||||
@ -489,8 +490,9 @@ bool PeepholeOptimizer::optimizeCopyOrBitcast(MachineInstr *MI) {
|
||||
/// isLoadFoldable - Check whether MI is a candidate for folding into a later
|
||||
/// instruction. We only fold loads to virtual registers and the virtual
|
||||
/// register defined has a single use.
|
||||
bool PeepholeOptimizer::isLoadFoldable(MachineInstr *MI,
|
||||
unsigned &FoldAsLoadDefReg) {
|
||||
bool PeepholeOptimizer::isLoadFoldable(
|
||||
MachineInstr *MI,
|
||||
SmallSet<unsigned, 16> &FoldAsLoadDefCandidates) {
|
||||
if (!MI->canFoldAsLoad() || !MI->mayLoad())
|
||||
return false;
|
||||
const MCInstrDesc &MCID = MI->getDesc();
|
||||
@ -504,7 +506,7 @@ bool PeepholeOptimizer::isLoadFoldable(MachineInstr *MI,
|
||||
if (!MI->getOperand(0).getSubReg() &&
|
||||
TargetRegisterInfo::isVirtualRegister(Reg) &&
|
||||
MRI->hasOneNonDBGUse(Reg)) {
|
||||
FoldAsLoadDefReg = Reg;
|
||||
FoldAsLoadDefCandidates.insert(Reg);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -570,18 +572,14 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
|
||||
|
||||
bool Changed = false;
|
||||
|
||||
SmallPtrSet<MachineInstr*, 8> LocalMIs;
|
||||
SmallSet<unsigned, 4> ImmDefRegs;
|
||||
DenseMap<unsigned, MachineInstr*> ImmDefMIs;
|
||||
unsigned FoldAsLoadDefReg;
|
||||
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
|
||||
MachineBasicBlock *MBB = &*I;
|
||||
|
||||
bool SeenMoveImm = false;
|
||||
LocalMIs.clear();
|
||||
ImmDefRegs.clear();
|
||||
ImmDefMIs.clear();
|
||||
FoldAsLoadDefReg = 0;
|
||||
SmallPtrSet<MachineInstr*, 8> LocalMIs;
|
||||
SmallSet<unsigned, 4> ImmDefRegs;
|
||||
DenseMap<unsigned, MachineInstr*> ImmDefMIs;
|
||||
SmallSet<unsigned, 16> FoldAsLoadDefCandidates;
|
||||
|
||||
for (MachineBasicBlock::iterator
|
||||
MII = I->begin(), MIE = I->end(); MII != MIE; ) {
|
||||
@ -595,15 +593,15 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
|
||||
continue;
|
||||
|
||||
// If there exists an instruction which belongs to the following
|
||||
// categories, we will discard the load candidate.
|
||||
// categories, we will discard the load candidates.
|
||||
if (MI->isPosition() || MI->isPHI() || MI->isImplicitDef() ||
|
||||
MI->isKill() || MI->isInlineAsm() ||
|
||||
MI->hasUnmodeledSideEffects()) {
|
||||
FoldAsLoadDefReg = 0;
|
||||
FoldAsLoadDefCandidates.clear();
|
||||
continue;
|
||||
}
|
||||
if (MI->mayStore() || MI->isCall())
|
||||
FoldAsLoadDefReg = 0;
|
||||
FoldAsLoadDefCandidates.clear();
|
||||
|
||||
if (((MI->isBitcast() || MI->isCopy()) && optimizeCopyOrBitcast(MI)) ||
|
||||
(MI->isCompare() && optimizeCmpInstr(MI, MBB)) ||
|
||||
@ -630,30 +628,41 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
|
||||
// Check whether MI is a load candidate for folding into a later
|
||||
// instruction. If MI is not a candidate, check whether we can fold an
|
||||
// earlier load into MI.
|
||||
if (!isLoadFoldable(MI, FoldAsLoadDefReg) && FoldAsLoadDefReg) {
|
||||
if (!isLoadFoldable(MI, FoldAsLoadDefCandidates) &&
|
||||
!FoldAsLoadDefCandidates.empty()) {
|
||||
// We need to fold load after optimizeCmpInstr, since optimizeCmpInstr
|
||||
// can enable folding by converting SUB to CMP.
|
||||
// Save FoldAsLoadDefReg because optimizeLoadInstr() resets it and we
|
||||
// need it for markUsesInDebugValueAsUndef().
|
||||
unsigned FoldedReg = FoldAsLoadDefReg;
|
||||
MachineInstr *DefMI = 0;
|
||||
MachineInstr *FoldMI = TII->optimizeLoadInstr(MI, MRI,
|
||||
FoldAsLoadDefReg, DefMI);
|
||||
if (FoldMI) {
|
||||
// Update LocalMIs since we replaced MI with FoldMI and deleted DefMI.
|
||||
DEBUG(dbgs() << "Replacing: " << *MI);
|
||||
DEBUG(dbgs() << " With: " << *FoldMI);
|
||||
LocalMIs.erase(MI);
|
||||
LocalMIs.erase(DefMI);
|
||||
LocalMIs.insert(FoldMI);
|
||||
MI->eraseFromParent();
|
||||
DefMI->eraseFromParent();
|
||||
MRI->markUsesInDebugValueAsUndef(FoldedReg);
|
||||
++NumLoadFold;
|
||||
|
||||
// MI is replaced with FoldMI.
|
||||
Changed = true;
|
||||
continue;
|
||||
const MCInstrDesc &MIDesc = MI->getDesc();
|
||||
for (unsigned i = MIDesc.getNumDefs(); i != MIDesc.getNumOperands();
|
||||
++i) {
|
||||
const MachineOperand &MOp = MI->getOperand(i);
|
||||
if (!MOp.isReg())
|
||||
continue;
|
||||
unsigned TryFoldReg = MOp.getReg();
|
||||
if (FoldAsLoadDefCandidates.count(TryFoldReg)) {
|
||||
MachineInstr *DefMI = 0;
|
||||
MachineInstr *FoldMI = TII->optimizeLoadInstr(MI, MRI, TryFoldReg,
|
||||
DefMI);
|
||||
if (FoldMI) {
|
||||
// Update LocalMIs since we replaced MI with FoldMI and deleted
|
||||
// DefMI.
|
||||
DEBUG(dbgs() << "Replacing: " << *MI);
|
||||
DEBUG(dbgs() << " With: " << *FoldMI);
|
||||
LocalMIs.erase(MI);
|
||||
LocalMIs.erase(DefMI);
|
||||
LocalMIs.insert(FoldMI);
|
||||
MI->eraseFromParent();
|
||||
DefMI->eraseFromParent();
|
||||
MRI->markUsesInDebugValueAsUndef(TryFoldReg);
|
||||
FoldAsLoadDefCandidates.erase(TryFoldReg);
|
||||
++NumLoadFold;
|
||||
// MI is replaced with FoldMI.
|
||||
Changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user