aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManman Ren <mren@apple.com>2012-07-11 19:35:12 +0000
committerManman Ren <mren@apple.com>2012-07-11 19:35:12 +0000
commit84ae7e9034ef4dd0b9c88c5cf0e5e91ab50a7ef1 (patch)
tree5bc419a39de470473836a8472e717d50c3448310
parent3fef29d88100881e7a52e570c30052e0d44c62ee (diff)
downloadexternal_llvm-84ae7e9034ef4dd0b9c88c5cf0e5e91ab50a7ef1.zip
external_llvm-84ae7e9034ef4dd0b9c88c5cf0e5e91ab50a7ef1.tar.gz
external_llvm-84ae7e9034ef4dd0b9c88c5cf0e5e91ab50a7ef1.tar.bz2
X86: Update to peephole optimization to move Movr0 before (Sub, Cmp) pair.
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
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp23
-rw-r--r--test/CodeGen/X86/jump_sign.ll12
2 files changed, 34 insertions, 1 deletions
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index eb30a87..921d215 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -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 &&
diff --git a/test/CodeGen/X86/jump_sign.ll b/test/CodeGen/X86/jump_sign.ll
index b868218..49f4176 100644
--- a/test/CodeGen/X86/jump_sign.ll
+++ b/test/CodeGen/X86/jump_sign.ll
@@ -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: