summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2014-05-14 16:14:45 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2014-05-14 16:14:45 +0000
commit202be0631841c7bdab1818d1c218765a5a4f99e8 (patch)
treed1ee8a2ae771951fb07d6651d1e3812ae1457a2d /test
parentf6741d6bddcba58a602c653d789c508b712ab6c8 (diff)
X86: If we have an instruction that sets a flag and a zero test on the input of that instruction try to eliminate the test.
For example tzcntl %edi, %ebx testl %edi, %edi je .label can be rewritten into tzcntl %edi, %ebx jb .label A minor complication is that tzcnt sets CF instead of ZF when the input is zero, we have to rewrite users of the flags from ZF to CF. Currently we recognize patterns using lzcnt, tzcnt and popcnt. Differential Revision: http://reviews.llvm.org/D3454 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208788 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r--test/CodeGen/X86/peep-test-4.ll76
1 files changed, 75 insertions, 1 deletions
diff --git a/test/CodeGen/X86/peep-test-4.ll b/test/CodeGen/X86/peep-test-4.ll
index 884ee7c2ba2..1ae621fb1f5 100644
--- a/test/CodeGen/X86/peep-test-4.ll
+++ b/test/CodeGen/X86/peep-test-4.ll
@@ -1,5 +1,6 @@
-; RUN: llc < %s -mtriple=x86_64-pc-linux -mattr=+bmi,+bmi2,+popcnt | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64-pc-linux -mattr=+bmi,+bmi2,+popcnt,+lzcnt | FileCheck %s
declare void @foo(i32)
+declare void @foo32(i32)
declare void @foo64(i64)
; CHECK-LABEL: neg:
@@ -189,3 +190,76 @@ bb:
return:
ret void
}
+
+; CHECK-LABEL: testCTZ
+; CHECK: tzcntq
+; CHECK-NOT: test
+; CHECK: cmovaeq
+declare i64 @llvm.cttz.i64(i64, i1)
+define i64 @testCTZ(i64 %v) nounwind {
+ %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
+ %tobool = icmp eq i64 %v, 0
+ %cond = select i1 %tobool, i64 255, i64 %cnt
+ ret i64 %cond
+}
+
+; CHECK-LABEL: testCTZ2
+; CHECK: tzcntl
+; CHECK-NEXT: jb
+; CHECK: jmp foo
+declare i32 @llvm.cttz.i32(i32, i1)
+define void @testCTZ2(i32 %v) nounwind {
+ %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
+ %cmp = icmp eq i32 %v, 0
+ br i1 %cmp, label %return, label %bb
+
+bb:
+ tail call void @foo(i32 %cnt)
+ br label %return
+
+return:
+ tail call void @foo32(i32 %cnt)
+ ret void
+}
+
+; CHECK-LABEL: testCTZ3
+; CHECK: tzcntl
+; CHECK-NEXT: jae
+; CHECK: jmp foo
+define void @testCTZ3(i32 %v) nounwind {
+ %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
+ %cmp = icmp ne i32 %v, 0
+ br i1 %cmp, label %return, label %bb
+
+bb:
+ tail call void @foo(i32 %cnt)
+ br label %return
+
+return:
+ tail call void @foo32(i32 %cnt)
+ ret void
+}
+
+; CHECK-LABEL: testCLZ
+; CHECK: lzcntq
+; CHECK-NOT: test
+; CHECK: cmovaeq
+declare i64 @llvm.ctlz.i64(i64, i1)
+define i64 @testCLZ(i64 %v) nounwind {
+ %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
+ %tobool = icmp ne i64 %v, 0
+ %cond = select i1 %tobool, i64 %cnt, i64 255
+ ret i64 %cond
+}
+
+; CHECK-LABEL: testPOPCNT
+; CHECK: popcntq
+; CHECK-NOT: test
+; CHECK: cmovneq
+declare i64 @llvm.ctpop.i64(i64)
+define i64 @testPOPCNT(i64 %v) nounwind {
+ %cnt = tail call i64 @llvm.ctpop.i64(i64 %v)
+ %tobool = icmp ne i64 %v, 0
+ %cond = select i1 %tobool, i64 %cnt, i64 255
+ ret i64 %cond
+}