1; RUN: llc < %s -mtriple=x86_64-pc-linux -mattr=+bmi,+lzcnt | FileCheck %s
2
3; LZCNT and TZCNT will always produce the operand size when the input operand
4; is zero. This test is to verify that we efficiently select LZCNT/TZCNT
5; based on the fact that the 'icmp+select' sequence is always redundant
6; in every function defined below.
7
8
9define i16 @test1_ctlz(i16 %v) {
10  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
11  %tobool = icmp eq i16 %v, 0
12  %cond = select i1 %tobool, i16 16, i16 %cnt
13  ret i16 %cond
14}
15; CHECK-LABEL: test1_ctlz
16; CHECK: lzcnt
17; CHECK-NEXT: ret
18
19
20define i32 @test2_ctlz(i32 %v) {
21  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
22  %tobool = icmp eq i32 %v, 0
23  %cond = select i1 %tobool, i32 32, i32 %cnt
24  ret i32 %cond
25}
26; CHECK-LABEL: test2_ctlz
27; CHECK: lzcnt
28; CHECK-NEXT: ret
29
30
31define i64 @test3_ctlz(i64 %v) {
32  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
33  %tobool = icmp eq i64 %v, 0
34  %cond = select i1 %tobool, i64 64, i64 %cnt
35  ret i64 %cond
36}
37; CHECK-LABEL: test3_ctlz
38; CHECK: lzcnt
39; CHECK-NEXT: ret
40
41
42define i16 @test4_ctlz(i16 %v) {
43  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
44  %tobool = icmp eq i16 0, %v
45  %cond = select i1 %tobool, i16 16, i16 %cnt
46  ret i16 %cond
47}
48; CHECK-LABEL: test4_ctlz
49; CHECK: lzcnt
50; CHECK-NEXT: ret
51
52
53define i32 @test5_ctlz(i32 %v) {
54  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
55  %tobool = icmp eq i32 0, %v
56  %cond = select i1 %tobool, i32 32, i32 %cnt
57  ret i32 %cond
58}
59; CHECK-LABEL: test5_ctlz
60; CHECK: lzcnt
61; CHECK-NEXT: ret
62
63
64define i64 @test6_ctlz(i64 %v) {
65  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
66  %tobool = icmp eq i64 0, %v
67  %cond = select i1 %tobool, i64 64, i64 %cnt
68  ret i64 %cond
69}
70; CHECK-LABEL: test6_ctlz
71; CHECK: lzcnt
72; CHECK-NEXT: ret
73
74
75define i16 @test10_ctlz(i16* %ptr) {
76  %v = load i16, i16* %ptr
77  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
78  %tobool = icmp eq i16 %v, 0
79  %cond = select i1 %tobool, i16 16, i16 %cnt
80  ret i16 %cond
81}
82; CHECK-LABEL: test10_ctlz
83; CHECK-NOT: movw
84; CHECK: lzcnt
85; CHECK-NEXT: ret
86
87
88define i32 @test11_ctlz(i32* %ptr) {
89  %v = load i32, i32* %ptr
90  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
91  %tobool = icmp eq i32 %v, 0
92  %cond = select i1 %tobool, i32 32, i32 %cnt
93  ret i32 %cond
94}
95; CHECK-LABEL: test11_ctlz
96; CHECK-NOT: movd
97; CHECK: lzcnt
98; CHECK-NEXT: ret
99
100
101define i64 @test12_ctlz(i64* %ptr) {
102  %v = load i64, i64* %ptr
103  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
104  %tobool = icmp eq i64 %v, 0
105  %cond = select i1 %tobool, i64 64, i64 %cnt
106  ret i64 %cond
107}
108; CHECK-LABEL: test12_ctlz
109; CHECK-NOT: movq
110; CHECK: lzcnt
111; CHECK-NEXT: ret
112
113
114define i16 @test13_ctlz(i16* %ptr) {
115  %v = load i16, i16* %ptr
116  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
117  %tobool = icmp eq i16 0, %v
118  %cond = select i1 %tobool, i16 16, i16 %cnt
119  ret i16 %cond
120}
121; CHECK-LABEL: test13_ctlz
122; CHECK-NOT: movw
123; CHECK: lzcnt
124; CHECK-NEXT: ret
125
126
127define i32 @test14_ctlz(i32* %ptr) {
128  %v = load i32, i32* %ptr
129  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
130  %tobool = icmp eq i32 0, %v
131  %cond = select i1 %tobool, i32 32, i32 %cnt
132  ret i32 %cond
133}
134; CHECK-LABEL: test14_ctlz
135; CHECK-NOT: movd
136; CHECK: lzcnt
137; CHECK-NEXT: ret
138
139
140define i64 @test15_ctlz(i64* %ptr) {
141  %v = load i64, i64* %ptr
142  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
143  %tobool = icmp eq i64 0, %v
144  %cond = select i1 %tobool, i64 64, i64 %cnt
145  ret i64 %cond
146}
147; CHECK-LABEL: test15_ctlz
148; CHECK-NOT: movq
149; CHECK: lzcnt
150; CHECK-NEXT: ret
151
152
153define i16 @test1_cttz(i16 %v) {
154  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
155  %tobool = icmp eq i16 %v, 0
156  %cond = select i1 %tobool, i16 16, i16 %cnt
157  ret i16 %cond
158}
159; CHECK-LABEL: test1_cttz
160; CHECK: tzcnt
161; CHECK-NEXT: ret
162
163
164define i32 @test2_cttz(i32 %v) {
165  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
166  %tobool = icmp eq i32 %v, 0
167  %cond = select i1 %tobool, i32 32, i32 %cnt
168  ret i32 %cond
169}
170; CHECK-LABEL: test2_cttz
171; CHECK: tzcnt
172; CHECK-NEXT: ret
173
174
175define i64 @test3_cttz(i64 %v) {
176  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
177  %tobool = icmp eq i64 %v, 0
178  %cond = select i1 %tobool, i64 64, i64 %cnt
179  ret i64 %cond
180}
181; CHECK-LABEL: test3_cttz
182; CHECK: tzcnt
183; CHECK-NEXT: ret
184
185
186define i16 @test4_cttz(i16 %v) {
187  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
188  %tobool = icmp eq i16 0, %v
189  %cond = select i1 %tobool, i16 16, i16 %cnt
190  ret i16 %cond
191}
192; CHECK-LABEL: test4_cttz
193; CHECK: tzcnt
194; CHECK-NEXT: ret
195
196
197define i32 @test5_cttz(i32 %v) {
198  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
199  %tobool = icmp eq i32 0, %v
200  %cond = select i1 %tobool, i32 32, i32 %cnt
201  ret i32 %cond
202}
203; CHECK-LABEL: test5_cttz
204; CHECK: tzcnt
205; CHECK-NEXT: ret
206
207
208define i64 @test6_cttz(i64 %v) {
209  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
210  %tobool = icmp eq i64 0, %v
211  %cond = select i1 %tobool, i64 64, i64 %cnt
212  ret i64 %cond
213}
214; CHECK-LABEL: test6_cttz
215; CHECK: tzcnt
216; CHECK-NEXT: ret
217
218
219define i16 @test10_cttz(i16* %ptr) {
220  %v = load i16, i16* %ptr
221  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
222  %tobool = icmp eq i16 %v, 0
223  %cond = select i1 %tobool, i16 16, i16 %cnt
224  ret i16 %cond
225}
226; CHECK-LABEL: test10_cttz
227; CHECK-NOT: movw
228; CHECK: tzcnt
229; CHECK-NEXT: ret
230
231
232define i32 @test11_cttz(i32* %ptr) {
233  %v = load i32, i32* %ptr
234  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
235  %tobool = icmp eq i32 %v, 0
236  %cond = select i1 %tobool, i32 32, i32 %cnt
237  ret i32 %cond
238}
239; CHECK-LABEL: test11_cttz
240; CHECK-NOT: movd
241; CHECK: tzcnt
242; CHECK-NEXT: ret
243
244
245define i64 @test12_cttz(i64* %ptr) {
246  %v = load i64, i64* %ptr
247  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
248  %tobool = icmp eq i64 %v, 0
249  %cond = select i1 %tobool, i64 64, i64 %cnt
250  ret i64 %cond
251}
252; CHECK-LABEL: test12_cttz
253; CHECK-NOT: movq
254; CHECK: tzcnt
255; CHECK-NEXT: ret
256
257
258define i16 @test13_cttz(i16* %ptr) {
259  %v = load i16, i16* %ptr
260  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
261  %tobool = icmp eq i16 0, %v
262  %cond = select i1 %tobool, i16 16, i16 %cnt
263  ret i16 %cond
264}
265; CHECK-LABEL: test13_cttz
266; CHECK-NOT: movw
267; CHECK: tzcnt
268; CHECK-NEXT: ret
269
270
271define i32 @test14_cttz(i32* %ptr) {
272  %v = load i32, i32* %ptr
273  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
274  %tobool = icmp eq i32 0, %v
275  %cond = select i1 %tobool, i32 32, i32 %cnt
276  ret i32 %cond
277}
278; CHECK-LABEL: test14_cttz
279; CHECK-NOT: movd
280; CHECK: tzcnt
281; CHECK-NEXT: ret
282
283
284define i64 @test15_cttz(i64* %ptr) {
285  %v = load i64, i64* %ptr
286  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
287  %tobool = icmp eq i64 0, %v
288  %cond = select i1 %tobool, i64 64, i64 %cnt
289  ret i64 %cond
290}
291; CHECK-LABEL: test15_cttz
292; CHECK-NOT: movq
293; CHECK: tzcnt
294; CHECK-NEXT: ret
295
296
297define i16 @test4b_ctlz(i16 %v) {
298  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
299  %tobool = icmp ne i16 %v, 0
300  %cond = select i1 %tobool, i16 %cnt, i16 16
301  ret i16 %cond
302}
303; CHECK-LABEL: test4b_ctlz
304; CHECK: lzcnt
305; CHECK-NEXT: ret
306
307
308define i32 @test5b_ctlz(i32 %v) {
309  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
310  %tobool = icmp ne i32 %v, 0
311  %cond = select i1 %tobool, i32 %cnt, i32 32
312  ret i32 %cond
313}
314; CHECK-LABEL: test5b_ctlz
315; CHECK: lzcnt
316; CHECK-NEXT: ret
317
318
319define i64 @test6b_ctlz(i64 %v) {
320  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
321  %tobool = icmp ne i64 %v, 0
322  %cond = select i1 %tobool, i64 %cnt, i64 64
323  ret i64 %cond
324}
325; CHECK-LABEL: test6b_ctlz
326; CHECK: lzcnt
327; CHECK-NEXT: ret
328
329
330define i16 @test4b_cttz(i16 %v) {
331  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
332  %tobool = icmp ne i16 %v, 0
333  %cond = select i1 %tobool, i16 %cnt, i16 16
334  ret i16 %cond
335}
336; CHECK-LABEL: test4b_cttz
337; CHECK: tzcnt
338; CHECK-NEXT: ret
339
340
341define i32 @test5b_cttz(i32 %v) {
342  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
343  %tobool = icmp ne i32 %v, 0
344  %cond = select i1 %tobool, i32 %cnt, i32 32
345  ret i32 %cond
346}
347; CHECK-LABEL: test5b_cttz
348; CHECK: tzcnt
349; CHECK-NEXT: ret
350
351
352define i64 @test6b_cttz(i64 %v) {
353  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
354  %tobool = icmp ne i64 %v, 0
355  %cond = select i1 %tobool, i64 %cnt, i64 64
356  ret i64 %cond
357}
358; CHECK-LABEL: test6b_cttz
359; CHECK: tzcnt
360; CHECK-NEXT: ret
361
362
363declare i64 @llvm.cttz.i64(i64, i1)
364declare i32 @llvm.cttz.i32(i32, i1)
365declare i16 @llvm.cttz.i16(i16, i1)
366declare i64 @llvm.ctlz.i64(i64, i1)
367declare i32 @llvm.ctlz.i32(i32, i1)
368declare i16 @llvm.ctlz.i16(i16, i1)
369
370