X86: Update to peephole optimization to move Movr0 before (Sub, Cmp) pair.
authorManman Ren <mren@apple.com>
Wed, 11 Jul 2012 19:35:12 +0000 (19:35 +0000)
committerManman Ren <mren@apple.com>
Wed, 11 Jul 2012 19:35:12 +0000 (19:35 +0000)
When Movr0 is between sub and cmp, we move Movr0 before sub if it enables
removal of Cmp.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160066 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86InstrInfo.cpp
test/CodeGen/X86/jump_sign.ll

index eb30a870c5ab03a8f74d1aed0fbf310118c6961c..921d2150f62b648429b7e46dffbfd75bc821dd51 100644 (file)
@@ -3110,6 +3110,7 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2,
       RE = CmpInstr->getParent() == MI->getParent() ?
            MachineBasicBlock::reverse_iterator(++Def) /* points to MI */ :
            CmpInstr->getParent()->rend();
+  MachineInstr *Movr0Inst = 0;
   for (; RI != RE; ++RI) {
     MachineInstr *Instr = &*RI;
     // Check whether CmpInstr can be made redundant by the current instruction.
@@ -3119,10 +3120,24 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2,
     }
 
     if (Instr->modifiesRegister(X86::EFLAGS, TRI) ||
-        Instr->readsRegister(X86::EFLAGS, TRI))
+        Instr->readsRegister(X86::EFLAGS, TRI)) {
       // This instruction modifies or uses EFLAGS.
+
+      // MOV32r0 etc. are implemented with xor which clobbers condition code.
+      // They are safe to move up, if the definition to EFLAGS is dead and
+      // earlier instructions do not read or write EFLAGS.
+      if (!Movr0Inst && (Instr->getOpcode() == X86::MOV8r0 ||
+           Instr->getOpcode() == X86::MOV16r0 ||
+           Instr->getOpcode() == X86::MOV32r0 ||
+           Instr->getOpcode() == X86::MOV64r0) &&
+          Instr->registerDefIsDead(X86::EFLAGS, TRI)) {
+        Movr0Inst = Instr;
+        continue;
+      }
+
       // We can't remove CmpInstr.
       return false;
+    }
   }
 
   // Return false if no candidates exist.
@@ -3204,6 +3219,12 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2,
         return false;
   }
 
+  // Move Movr0Inst to the place right before Sub.
+  if (Movr0Inst) {
+    Sub->getParent()->remove(Movr0Inst);
+    Sub->getParent()->insert(MachineBasicBlock::iterator(Sub), Movr0Inst);
+  }
+
   // Make sure Sub instruction defines EFLAGS.
   assert(Sub->getNumOperands() >= 4 && Sub->getOperand(3).isReg() &&
          Sub->getOperand(3).getReg() == X86::EFLAGS &&
index b868218ecad0a44c286e3fa5441543db38de0cd7..49f41767a2d5a84ed81383727e139caea62333ce 100644 (file)
@@ -137,6 +137,18 @@ if.else:
   %add = add nsw i32 %sub, 1
   ret i32 %add
 }
+; rdar://11830760
+; When Movr0 is between sub and cmp, we need to move "Movr0" before sub.
+define i32 @l4(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: l4:
+; CHECK: sub
+; CHECK-NOT: cmp
+  %cmp = icmp sgt i32 %b, %a
+  %sub = sub i32 %a, %b
+  %.sub = select i1 %cmp, i32 0, i32 %sub
+  ret i32 %.sub
+}
 ; rdar://11540023
 define i32 @n(i32 %x, i32 %y) nounwind {
 entry: