From 6259d51c91d7da9bf16114849236b5bdfa85f35e Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Sun, 30 Dec 2007 03:18:58 +0000 Subject: [PATCH] If we have a load of a global address that's not modified during the function, then go ahead and hoist it out of the loop. This is the result: $ cat a.c volatile int G; int A(int N) { for (; N > 0; --N) G++; } $ llc -o - -relocation-model=pic _A: ... LBB1_2: # bb movl L_G$non_lazy_ptr-"L1$pb"(%eax), %esi incl (%esi) incl %edx cmpl %ecx, %edx jne LBB1_2 # bb ... $ llc -o - -relocation-model=pic -machine-licm _A: ... movl L_G$non_lazy_ptr-"L1$pb"(%eax), %eax LBB1_2: # bb incl (%eax) incl %edx cmpl %ecx, %edx jne LBB1_2 # bb ... I'm limiting this to the MOV32rm x86 instruction for now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45444 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86InstrInfo.cpp | 54 +++++++++++++++++++++++++++++++-- lib/Target/X86/X86InstrInfo.h | 9 ++++++ 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 08a26e15d55..4f7d51e1634 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -144,6 +144,37 @@ bool X86InstrInfo::isReallyTriviallyReMaterializable(MachineInstr *MI) const { return true; } +/// isDefinedInEntryBlock - Goes through the entry block to see if the given +/// virtual register is indeed defined in the entry block. +/// +bool X86InstrInfo::isDefinedInEntryBlock(const MachineBasicBlock &Entry, + unsigned VReg) const { + assert(MRegisterInfo::isVirtualRegister(VReg) && + "Map only holds virtual registers!"); + MachineInstrMap.grow(VReg); + if (MachineInstrMap[VReg]) return true; + + MachineBasicBlock::const_iterator I = Entry.begin(), E = Entry.end(); + + for (; I != E; ++I) { + const MachineInstr &MI = *I; + unsigned NumOps = MI.getNumOperands(); + + for (unsigned i = 0; i < NumOps; ++i) { + const MachineOperand &MO = MI.getOperand(i); + + if(MO.isRegister() && MO.isDef() && + MRegisterInfo::isVirtualRegister(MO.getReg()) && + MO.getReg() == VReg) { + MachineInstrMap[VReg] = &MI; + return true; + } + } + } + + return false; +} + /// isReallySideEffectFree - If the M_MAY_HAVE_SIDE_EFFECTS flag is set, this /// method is called to determine if the specific instance of this instruction /// has side effects. This is useful in cases of instructions, like loads, which @@ -152,10 +183,25 @@ bool X86InstrInfo::isReallyTriviallyReMaterializable(MachineInstr *MI) const { bool X86InstrInfo::isReallySideEffectFree(MachineInstr *MI) const { switch (MI->getOpcode()) { default: break; + case X86::MOV32rm: + if (MI->getOperand(1).isRegister()) { + unsigned Reg = MI->getOperand(1).getReg(); + + // Loads from global addresses which aren't redefined in the function are + // side effect free. + if (MRegisterInfo::isVirtualRegister(Reg) && + isDefinedInEntryBlock(MI->getParent()->getParent()->front(), Reg) && + MI->getOperand(2).isImmediate() && + MI->getOperand(3).isRegister() && + MI->getOperand(4).isGlobalAddress() && + MI->getOperand(2).getImmedValue() == 1 && + MI->getOperand(3).getReg() == 0) + return true; + } + // FALLTHROUGH case X86::MOV8rm: case X86::MOV16rm: case X86::MOV16_rm: - case X86::MOV32rm: case X86::MOV32_rm: case X86::MOV64rm: case X86::LD_Fp64m: @@ -166,8 +212,10 @@ bool X86InstrInfo::isReallySideEffectFree(MachineInstr *MI) const { case X86::MMX_MOVD64rm: case X86::MMX_MOVQ64rm: // Loads from constant pools have no side effects - return MI->getOperand(1).isRegister() && MI->getOperand(2).isImmediate() && - MI->getOperand(3).isRegister() && MI->getOperand(4).isConstantPoolIndex() && + return MI->getOperand(1).isRegister() && + MI->getOperand(2).isImmediate() && + MI->getOperand(3).isRegister() && + MI->getOperand(4).isConstantPoolIndex() && MI->getOperand(1).getReg() == 0 && MI->getOperand(2).getImmedValue() == 1 && MI->getOperand(3).getReg() == 0; diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index 8f522af9449..589edac25cc 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -16,6 +16,8 @@ #include "llvm/Target/TargetInstrInfo.h" #include "X86RegisterInfo.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/Target/MRegisterInfo.h" namespace llvm { class X86RegisterInfo; @@ -223,6 +225,13 @@ namespace X86II { class X86InstrInfo : public TargetInstrInfo { X86TargetMachine &TM; const X86RegisterInfo RI; + mutable IndexedMap MachineInstrMap; + + /// isDefinedInEntryBlock - Goes through the entry block to see if the given + /// virtual register is indeed defined in the entry block. + /// + bool isDefinedInEntryBlock(const MachineBasicBlock &Entry, + unsigned VReg) const; public: X86InstrInfo(X86TargetMachine &tm);