xref: /llvm-project/llvm/test/CodeGen/AArch64/fold-csel-cttz-and.ll (revision db158c7c830807caeeb0691739c41f1d522029e9)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=aarch64 < %s | FileCheck %s
3
4;; Check the transformation
5;; CSEL 0, cttz, cc -> AND cttz numbits-1
6;; for cttz in the case of i32 and i64 respectively
7
8;; Cases for which the optimzation takes place
9define 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
15; CHECK-NEXT:    ret
16entry:
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
20  ret i32 %2
21}
22
23define 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
29; CHECK-NEXT:    ret
30entry:
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
34  ret i64 %2
35}
36
37define 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
43; CHECK-NEXT:    ret
44entry:
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
48  ret i32 %2
49}
50
51define 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
57; CHECK-NEXT:    ret
58entry:
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
62  ret i64 %2
63}
64
65define 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
71; CHECK-NEXT:    ret
72entry:
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
77  ret i32 %3
78}
79
80;; Cases for which the optimization does not take place
81define 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
88; CHECK-NEXT:    ret
89entry:
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
93  ret i32 %2
94}
95
96define 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
103; CHECK-NEXT:    ret
104entry:
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
108  ret i32 %2
109}
110
111define 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
119; CHECK-NEXT:    ret
120entry:
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
124  ret i32 %2
125}
126
127define 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
133; CHECK-NEXT:    ret
134entry:
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
138  ret i32 %2
139}
140
141define 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
148; CHECK-NEXT:    ret
149entry:
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
153  ret i32 %2
154}
155
156declare i32 @llvm.cttz.i32(i32, i1)
157
158declare i64 @llvm.cttz.i64(i64, i1)
159
160declare i32 @llvm.ctlz.i32(i32, i1)
161