aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2013-05-18 01:02:03 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2013-05-18 01:02:03 +0000
commit8a55c2ecd4d7648a6564091d428e18ec2146ff8e (patch)
tree20f6df4c43b569d628fc4eb455d6cf867e89d91b
parent24623dcd249939cfa35af4771b61aa47a5cbffc8 (diff)
downloadexternal_llvm-8a55c2ecd4d7648a6564091d428e18ec2146ff8e.zip
external_llvm-8a55c2ecd4d7648a6564091d428e18ec2146ff8e.tar.gz
external_llvm-8a55c2ecd4d7648a6564091d428e18ec2146ff8e.tar.bz2
X86: Bad peephole interaction between adc, MOV32r0
The peephole tries to reorder MOV32r0 instructions such that they are before the instruction that modifies EFLAGS. The problem is that the peephole does not consider the case where the instruction that modifies EFLAGS also depends on the previous state of EFLAGS. Instead, walk backwards until we find an instruction that has a def for EFLAGS but does not have a use. If we find such an instruction, insert the MOV32r0 before it. If it cannot find such an instruction, skip the optimization. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182184 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp21
-rw-r--r--test/CodeGen/X86/pr16031.ll27
2 files changed, 45 insertions, 3 deletions
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 582add7..afa43c1 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -3449,10 +3449,25 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2,
// The instruction to be updated is either Sub or MI.
Sub = IsCmpZero ? MI : Sub;
- // Move Movr0Inst to the place right before Sub.
+ // Move Movr0Inst to the appropriate place before Sub.
if (Movr0Inst) {
- Sub->getParent()->remove(Movr0Inst);
- Sub->getParent()->insert(MachineBasicBlock::iterator(Sub), Movr0Inst);
+ // Look backwards until we find a def that doesn't use the current EFLAGS.
+ Def = Sub;
+ MachineBasicBlock::reverse_iterator
+ InsertI = MachineBasicBlock::reverse_iterator(++Def),
+ InsertE = Sub->getParent()->rend();
+ for (; InsertI != InsertE; ++InsertI) {
+ MachineInstr *Instr = &*InsertI;
+ if (!Instr->readsRegister(X86::EFLAGS, TRI) &&
+ Instr->modifiesRegister(X86::EFLAGS, TRI)) {
+ Sub->getParent()->remove(Movr0Inst);
+ Instr->getParent()->insert(MachineBasicBlock::iterator(Instr),
+ Movr0Inst);
+ break;
+ }
+ }
+ if (InsertI == InsertE)
+ return false;
}
// Make sure Sub instruction defines EFLAGS and mark the def live.
diff --git a/test/CodeGen/X86/pr16031.ll b/test/CodeGen/X86/pr16031.ll
new file mode 100644
index 0000000..4721173
--- /dev/null
+++ b/test/CodeGen/X86/pr16031.ll
@@ -0,0 +1,27 @@
+; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -mcpu=corei7-avx | FileCheck %s
+
+; CHECK: main:
+; CHECK: pushl %esi
+; CHECK-NEXT: movl $-12, %eax
+; CHECK-NEXT: movl $-1, %edx
+; CHECK-NEXT: testb $1, 8(%esp)
+; CHECK-NEXT: cmovel %edx, %eax
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: movl %eax, %esi
+; CHECK-NEXT: addl $-1, %esi
+; CHECK-NEXT: movl $-1, %esi
+; CHECK-NEXT: adcl $-1, %esi
+; CHECK-NEXT: cmovsl %ecx, %eax
+; CHECK-NEXT: cmovsl %ecx, %edx
+; CHECK-NEXT: popl %esi
+define i64 @main(i1 %tobool1) nounwind {
+entry:
+ %0 = zext i1 %tobool1 to i32
+ %. = xor i32 %0, 1
+ %.21 = select i1 %tobool1, i32 -12, i32 -1
+ %conv = sext i32 %.21 to i64
+ %1 = add i64 %conv, -1
+ %cmp10 = icmp slt i64 %1, 0
+ %sub17 = select i1 %cmp10, i64 0, i64 %conv
+ ret i64 %sub17
+}