1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=aarch64 < %s | FileCheck %s
4 ;; Check the transformation
5 ;; CSEL 0, cttz, cc -> AND cttz numbits-1
6 ;; for cttz in the case of i32 and i64 respectively
8 ;; Cases for which the optimzation takes place
9 define i32 @cttzi32(i32 %x) {
10 ; CHECK-LABEL: cttzi32:
11 ; CHECK: // %bb.0: // %entry
12 ; CHECK-NEXT: rbit w8, w0
13 ; CHECK-NEXT: clz w8, w8
14 ; CHECK-NEXT: and w0, w8, #0x1f
17 %0 = call i32 @llvm.cttz.i32(i32 %x, i1 true)
18 %1 = icmp eq i32 %x, 0
19 %2 = select i1 %1, i32 0, i32 %0
23 define i64 @cttzi64(i64 %x) {
24 ; CHECK-LABEL: cttzi64:
25 ; CHECK: // %bb.0: // %entry
26 ; CHECK-NEXT: rbit x8, x0
27 ; CHECK-NEXT: clz x8, x8
28 ; CHECK-NEXT: and x0, x8, #0x3f
31 %0 = call i64 @llvm.cttz.i64(i64 %x, i1 true)
32 %1 = icmp eq i64 %x, 0
33 %2 = select i1 %1, i64 0, i64 %0
37 define i32 @cttzi32ne(i32 %x) {
38 ; CHECK-LABEL: cttzi32ne:
39 ; CHECK: // %bb.0: // %entry
40 ; CHECK-NEXT: rbit w8, w0
41 ; CHECK-NEXT: clz w8, w8
42 ; CHECK-NEXT: and w0, w8, #0x1f
45 %0 = call i32 @llvm.cttz.i32(i32 %x, i1 true)
46 %1 = icmp ne i32 %x, 0
47 %2 = select i1 %1, i32 %0, i32 0
51 define i64 @cttzi64ne(i64 %x) {
52 ; CHECK-LABEL: cttzi64ne:
53 ; CHECK: // %bb.0: // %entry
54 ; CHECK-NEXT: rbit x8, x0
55 ; CHECK-NEXT: clz x8, x8
56 ; CHECK-NEXT: and x0, x8, #0x3f
59 %0 = call i64 @llvm.cttz.i64(i64 %x, i1 true)
60 %1 = icmp ne i64 %x, 0
61 %2 = select i1 %1, i64 %0, i64 0
65 define i32 @cttztrunc(i64 %x) {
66 ; CHECK-LABEL: cttztrunc:
67 ; CHECK: // %bb.0: // %entry
68 ; CHECK-NEXT: rbit x8, x0
69 ; CHECK-NEXT: clz x8, x8
70 ; CHECK-NEXT: and w0, w8, #0x3f
73 %0 = call i64 @llvm.cttz.i64(i64 %x, i1 true)
74 %1 = icmp eq i64 %x, 0
75 %2 = select i1 %1, i64 0, i64 %0
76 %3 = trunc i64 %2 to i32
80 ;; Cases for which the optimization does not take place
81 define i32 @cttzne(i32 %x) {
82 ; CHECK-LABEL: cttzne:
83 ; CHECK: // %bb.0: // %entry
84 ; CHECK-NEXT: rbit w8, w0
85 ; CHECK-NEXT: cmp w0, #0
86 ; CHECK-NEXT: clz w8, w8
87 ; CHECK-NEXT: csel w0, wzr, w8, ne
90 %0 = call i32 @llvm.cttz.i32(i32 %x, i1 true)
91 %1 = icmp ne i32 %x, 0
92 %2 = select i1 %1, i32 0, i32 %0
96 define i32 @cttzxnot0(i32 %x) {
97 ; CHECK-LABEL: cttzxnot0:
98 ; CHECK: // %bb.0: // %entry
99 ; CHECK-NEXT: rbit w8, w0
100 ; CHECK-NEXT: cmp w0, #10
101 ; CHECK-NEXT: clz w8, w8
102 ; CHECK-NEXT: csel w0, wzr, w8, eq
105 %0 = call i32 @llvm.cttz.i32(i32 %x, i1 true)
106 %1 = icmp eq i32 %x, 10
107 %2 = select i1 %1, i32 0, i32 %0
111 define i32 @cttzlhsnot0(i32 %x) {
112 ; CHECK-LABEL: cttzlhsnot0:
113 ; CHECK: // %bb.0: // %entry
114 ; CHECK-NEXT: rbit w9, w0
115 ; CHECK-NEXT: mov w8, #10 // =0xa
116 ; CHECK-NEXT: cmp w0, #0
117 ; CHECK-NEXT: clz w9, w9
118 ; CHECK-NEXT: csel w0, w8, w9, eq
121 %0 = call i32 @llvm.cttz.i32(i32 %x, i1 true)
122 %1 = icmp eq i32 %x, 0
123 %2 = select i1 %1, i32 10, i32 %0
127 define i32 @notcttz(i32 %x) {
128 ; CHECK-LABEL: notcttz:
129 ; CHECK: // %bb.0: // %entry
130 ; CHECK-NEXT: clz w8, w0
131 ; CHECK-NEXT: cmp w0, #0
132 ; CHECK-NEXT: csel w0, wzr, w8, eq
135 %0 = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
136 %1 = icmp eq i32 %x, 0
137 %2 = select i1 %1, i32 0, i32 %0
141 define i32 @cttzlhsnotx(i32 %x, i32 %y) {
142 ; CHECK-LABEL: cttzlhsnotx:
143 ; CHECK: // %bb.0: // %entry
144 ; CHECK-NEXT: rbit w8, w0
145 ; CHECK-NEXT: cmp w1, #0
146 ; CHECK-NEXT: clz w8, w8
147 ; CHECK-NEXT: csel w0, wzr, w8, eq
150 %0 = call i32 @llvm.cttz.i32(i32 %x, i1 true)
151 %1 = icmp eq i32 %y, 0
152 %2 = select i1 %1, i32 0, i32 %0
156 declare i32 @llvm.cttz.i32(i32, i1)
158 declare i64 @llvm.cttz.i64(i64, i1)
160 declare i32 @llvm.ctlz.i32(i32, i1)