diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2014-05-14 16:14:45 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2014-05-14 16:14:45 +0000 |
commit | 202be0631841c7bdab1818d1c218765a5a4f99e8 (patch) | |
tree | d1ee8a2ae771951fb07d6651d1e3812ae1457a2d /test | |
parent | f6741d6bddcba58a602c653d789c508b712ab6c8 (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.ll | 76 |
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 +} |