diff options
author | Manman Ren <mren@apple.com> | 2012-07-28 16:48:01 +0000 |
---|---|---|
committer | Manman Ren <mren@apple.com> | 2012-07-28 16:48:01 +0000 |
commit | 0eb3edea9cb6819334173a7d288da85943201fe5 (patch) | |
tree | 77172a23d7618e5dbe447fc4b7536ba1a416deaf /lib/Target | |
parent | cdfbcdeeede52de472ae8187c0fb4ed4a014c2a3 (diff) | |
download | external_llvm-0eb3edea9cb6819334173a7d288da85943201fe5.zip external_llvm-0eb3edea9cb6819334173a7d288da85943201fe5.tar.gz external_llvm-0eb3edea9cb6819334173a7d288da85943201fe5.tar.bz2 |
X86 Peephole: fold loads to the source register operand if possible.
Machine CSE and other optimizations can remove instructions so folding
is possible at peephole while not possible at ISel.
rdar://10554090 and rdar://11873276
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160919 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/X86/X86InstrInfo.cpp | 69 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.h | 8 |
2 files changed, 77 insertions, 0 deletions
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 89a57b5..2bae2c6 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -3323,6 +3323,75 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2, return true; } +/// optimizeLoadInstr - Try to remove the load by folding it to a register +/// operand at the use. We fold the load instructions if and only if the +/// def and use are in the same BB. +MachineInstr* X86InstrInfo:: +optimizeLoadInstr(MachineInstr *MI, const MachineRegisterInfo *MRI, + SmallSet<unsigned, 4> &FoldAsLoadDefRegs, + MachineInstr *&DefMI) const { + if (MI->mayStore() || MI->isCall()) + // To be conservative, we don't fold the loads if there is a store in + // between. + FoldAsLoadDefRegs.clear(); + // We only fold loads to a virtual register. + if (MI->canFoldAsLoad()) { + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.getNumDefs() == 1) { + unsigned Reg = MI->getOperand(0).getReg(); + // To reduce compilation time, we check MRI->hasOneUse when inserting + // loads. It should be checked when processing uses of the load, since + // uses can be removed during peephole. + if (TargetRegisterInfo::isVirtualRegister(Reg) && MRI->hasOneUse(Reg)) { + FoldAsLoadDefRegs.insert(Reg); + return 0; + } + } + } + + // Collect information about virtual register operands of MI. + DenseMap<unsigned, unsigned> SrcVirtualRegToOp; + SmallSet<unsigned, 4> DstVirtualRegs; + for (unsigned i = 0, e = MI->getDesc().getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + if (MO.isDef()) + DstVirtualRegs.insert(Reg); + else if (FoldAsLoadDefRegs.count(Reg)) { + // Only handle the case where Reg is used in a single src operand. + if (SrcVirtualRegToOp.find(Reg) != SrcVirtualRegToOp.end()) + SrcVirtualRegToOp.erase(Reg); + else + SrcVirtualRegToOp.insert(std::make_pair(Reg, i)); + } + } + + for (DenseMap<unsigned, unsigned>::iterator SI = SrcVirtualRegToOp.begin(), + SE = SrcVirtualRegToOp.end(); SI != SE; SI++) { + // If the virtual register is updated by MI, we can't fold the load. + if (DstVirtualRegs.count(SI->first)) continue; + + // Check whether we can fold the def into this operand. + DefMI = MRI->getVRegDef(SI->first); + assert(DefMI); + bool SawStore = false; + if (!DefMI->isSafeToMove(this, 0, SawStore)) + continue; + + SmallVector<unsigned, 8> Ops; + Ops.push_back(SI->second); + MachineInstr *FoldMI = foldMemoryOperand(MI, Ops, DefMI); + if (!FoldMI) continue; + FoldAsLoadDefRegs.erase(SI->first); + return FoldMI; + } + return 0; +} + /// Expand2AddrUndef - Expand a single-def pseudo instruction to a two-addr /// instruction with two undef reads of the register being defined. This is /// used for mapping: diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index ec9b2e6..9205315 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -387,6 +387,14 @@ public: unsigned SrcReg2, int CmpMask, int CmpValue, const MachineRegisterInfo *MRI) const; + /// optimizeLoadInstr - Try to remove the load by folding it to a register + /// operand at the use. We fold the load instructions if and only if the + /// def and use are in the same BB. + virtual MachineInstr* optimizeLoadInstr(MachineInstr *MI, + const MachineRegisterInfo *MRI, + SmallSet<unsigned, 4> &FoldAsLoadDefRegs, + MachineInstr *&DefMI) const; + private: MachineInstr * convertToThreeAddressWithLEA(unsigned MIOpc, MachineFunction::iterator &MFI, |