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.

llvm-svn: 45444
This commit is contained in:
Bill Wendling 2007-12-30 03:18:58 +00:00
parent 330aaa79e0
commit 7749a9014b
2 changed files with 60 additions and 3 deletions

View File

@ -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;

View File

@ -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<const MachineInstr*, VirtReg2IndexFunctor> 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);