summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2017-09-06 06:28:08 +0000
committerChandler Carruth <chandlerc@gmail.com>2017-09-06 06:28:08 +0000
commit585bfc844318870ebdb10ff99e4edc20013fe3da (patch)
tree524b13392f284f37703ff6610a1224db1a20277f
parent5ebe94a84d6aba9e5c449a2c7913d3735dd7ea29 (diff)
downloadbcm5719-llvm-585bfc844318870ebdb10ff99e4edc20013fe3da.tar.gz
bcm5719-llvm-585bfc844318870ebdb10ff99e4edc20013fe3da.zip
[x86] Fix PR34377 by disabling cmov conversion when we relied on it
performing a zext of a register. On the PR there is discussion of how to more effectively handle this, but this patch prevents us from miscompiling code. Differential Revision: https://reviews.llvm.org/D37504 llvm-svn: 312620
-rw-r--r--llvm/lib/Target/X86/X86CmovConversion.cpp10
-rw-r--r--llvm/test/CodeGen/X86/cmov-into-branch.ll26
2 files changed, 32 insertions, 4 deletions
diff --git a/llvm/lib/Target/X86/X86CmovConversion.cpp b/llvm/lib/Target/X86/X86CmovConversion.cpp
index f7967004e20..e31a7949f0b 100644
--- a/llvm/lib/Target/X86/X86CmovConversion.cpp
+++ b/llvm/lib/Target/X86/X86CmovConversion.cpp
@@ -289,6 +289,16 @@ bool X86CmovConverterPass::collectCmovCandidates(
// Can't handle mixed conditions with memory operands.
SkipGroup = true;
}
+ // Check if we were relying on zero-extending behavior of the CMOV.
+ if (!SkipGroup &&
+ llvm::any_of(
+ MRI->use_nodbg_instructions(I.defs().begin()->getReg()),
+ [&](MachineInstr &UseI) {
+ return UseI.getOpcode() == X86::SUBREG_TO_REG;
+ }))
+ // FIXME: We should model the cost of using an explicit MOV to handle
+ // the zero-extension rather than just refusing to handle this.
+ SkipGroup = true;
continue;
}
// If Group is empty, keep looking for first CMOV in the range.
diff --git a/llvm/test/CodeGen/X86/cmov-into-branch.ll b/llvm/test/CodeGen/X86/cmov-into-branch.ll
index e3803950164..0a2246700e6 100644
--- a/llvm/test/CodeGen/X86/cmov-into-branch.ll
+++ b/llvm/test/CodeGen/X86/cmov-into-branch.ll
@@ -61,6 +61,24 @@ define i32 @test5(i32 %a, i32* nocapture %b, i32 %x, i32 %y) {
ret i32 %cond5
}
+; Zero-extended select.
+define void @test6(i32 %a, i32 %x, i32* %y.ptr, i64* %z.ptr) {
+; CHECK-LABEL: test6:
+; CHECK: # BB#0: # %entry
+; CHECK-NEXT: # kill: %ESI<def> %ESI<kill> %RSI<def>
+; CHECK-NEXT: testl %edi, %edi
+; CHECK-NEXT: cmovnsl (%rdx), %esi
+; CHECK-NEXT: movq %rsi, (%rcx)
+; CHECK-NEXT: retq
+entry:
+ %y = load i32, i32* %y.ptr
+ %cmp = icmp slt i32 %a, 0
+ %z = select i1 %cmp, i32 %x, i32 %y
+ %z.ext = zext i32 %z to i64
+ store i64 %z.ext, i64* %z.ptr
+ ret void
+}
+
; If a select is not obviously predictable, don't turn it into a branch.
define i32 @weighted_select1(i32 %a, i32 %b) {
; CHECK-LABEL: weighted_select1:
@@ -79,10 +97,10 @@ define i32 @weighted_select2(i32 %a, i32 %b) {
; CHECK-LABEL: weighted_select2:
; CHECK: # BB#0:
; CHECK-NEXT: testl %edi, %edi
-; CHECK-NEXT: jne .LBB5_2
+; CHECK-NEXT: jne .LBB6_2
; CHECK-NEXT: # BB#1: # %select.false
; CHECK-NEXT: movl %esi, %edi
-; CHECK-NEXT: .LBB5_2: # %select.end
+; CHECK-NEXT: .LBB6_2: # %select.end
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
%cmp = icmp ne i32 %a, 0
@@ -98,11 +116,11 @@ define i32 @weighted_select3(i32 %a, i32 %b) {
; CHECK-LABEL: weighted_select3:
; CHECK: # BB#0:
; CHECK-NEXT: testl %edi, %edi
-; CHECK-NEXT: je .LBB6_1
+; CHECK-NEXT: je .LBB7_1
; CHECK-NEXT: # BB#2: # %select.end
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB6_1: # %select.false
+; CHECK-NEXT: .LBB7_1: # %select.false
; CHECK-NEXT: movl %esi, %edi
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
OpenPOWER on IntegriCloud