If we have a load of a global address that's not modified during the
authorBill Wendling <isanbard@gmail.com>
Sun, 30 Dec 2007 03:18:58 +0000 (03:18 +0000)
committerBill Wendling <isanbard@gmail.com>
Sun, 30 Dec 2007 03:18:58 +0000 (03:18 +0000)
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
lib/Target/X86/X86InstrInfo.h

index 08a26e15d558f5513bddc91c73e0137de94f683b..4f7d51e1634d186b6295f4997e5d51251925fc3c 100644 (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;
index 8f522af944985931fdeecdc20c009a16c8c984f4..589edac25cc4e5ad6060f5abc91b00b9df158f2b 100644 (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);