1; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI
2; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT
3; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown < %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC
4
5
6define i64 @test1(i64 %A) {
7; ALL-LABEL: @test1(
8; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i64 @llvm.ctlz.i64(i64 %A, i1 false)
9; LZCNT-NEXT: ret i64 [[CTLZ]]
10; BMI: icmp eq i64 %A, 0
11; BMI: call i64 @llvm.ctlz.i64(i64 %A, i1 true)
12; GENERIC: icmp eq i64 %A, 0
13; GENERIC: call i64 @llvm.ctlz.i64(i64 %A, i1 true)
14entry:
15  %tobool = icmp eq i64 %A, 0
16  br i1 %tobool, label %cond.end, label %cond.true
17
18cond.true:                                        ; preds = %entry
19  %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
20  br label %cond.end
21
22cond.end:                                         ; preds = %entry, %cond.true
23  %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
24  ret i64 %cond
25}
26
27
28define i32 @test2(i32 %A) {
29; ALL-LABEL: @test2(
30; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i32 @llvm.ctlz.i32(i32 %A, i1 false)
31; LZCNT-NEXT: ret i32 [[CTLZ]]
32; BMI: icmp eq i32 %A, 0
33; BMI: call i32 @llvm.ctlz.i32(i32 %A, i1 true)
34; GENERIC: icmp eq i32 %A, 0
35; GENERIC: call i32 @llvm.ctlz.i32(i32 %A, i1 true)
36entry:
37  %tobool = icmp eq i32 %A, 0
38  br i1 %tobool, label %cond.end, label %cond.true
39
40cond.true:                                        ; preds = %entry
41  %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
42  br label %cond.end
43
44cond.end:                                         ; preds = %entry, %cond.true
45  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
46  ret i32 %cond
47}
48
49
50define signext i16 @test3(i16 signext %A) {
51; ALL-LABEL: @test3(
52; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i16 @llvm.ctlz.i16(i16 %A, i1 false)
53; LZCNT-NEXT: ret i16 [[CTLZ]]
54; BMI: icmp eq i16 %A, 0
55; BMI: call i16 @llvm.ctlz.i16(i16 %A, i1 true)
56; GENERIC: icmp eq i16 %A, 0
57; GENERIC: call i16 @llvm.ctlz.i16(i16 %A, i1 true)
58entry:
59  %tobool = icmp eq i16 %A, 0
60  br i1 %tobool, label %cond.end, label %cond.true
61
62cond.true:                                        ; preds = %entry
63  %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
64  br label %cond.end
65
66cond.end:                                         ; preds = %entry, %cond.true
67  %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
68  ret i16 %cond
69}
70
71
72define i64 @test1b(i64 %A) {
73; ALL-LABEL: @test1b(
74; LZCNT: icmp eq i64 %A, 0
75; LZCNT: call i64 @llvm.cttz.i64(i64 %A, i1 true)
76; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %A, i1 false)
77; BMI-NEXT: ret i64 [[CTTZ]]
78; GENERIC: icmp eq i64 %A, 0
79; GENERIC: call i64 @llvm.cttz.i64(i64 %A, i1 true)
80entry:
81  %tobool = icmp eq i64 %A, 0
82  br i1 %tobool, label %cond.end, label %cond.true
83
84cond.true:                                        ; preds = %entry
85  %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
86  br label %cond.end
87
88cond.end:                                         ; preds = %entry, %cond.true
89  %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
90  ret i64 %cond
91}
92
93
94define i32 @test2b(i32 %A) {
95; ALL-LABEL: @test2b(
96; LZCNT: icmp eq i32 %A, 0
97; LZCNT: call i32 @llvm.cttz.i32(i32 %A, i1 true)
98; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %A, i1 false)
99; BMI-NEXT: ret i32 [[CTTZ]]
100; GENERIC: icmp eq i32 %A, 0
101; GENERIC: call i32 @llvm.cttz.i32(i32 %A, i1 true)
102entry:
103  %tobool = icmp eq i32 %A, 0
104  br i1 %tobool, label %cond.end, label %cond.true
105
106cond.true:                                        ; preds = %entry
107  %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
108  br label %cond.end
109
110cond.end:                                         ; preds = %entry, %cond.true
111  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
112  ret i32 %cond
113}
114
115
116define signext i16 @test3b(i16 signext %A) {
117; ALL-LABEL: @test3b(
118; LZCNT: icmp eq i16 %A, 0
119; LZCNT: call i16 @llvm.cttz.i16(i16 %A, i1 true)
120; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i16 @llvm.cttz.i16(i16 %A, i1 false)
121; BMI-NEXT: ret i16 [[CTTZ]]
122; GENERIC: icmp eq i16 %A, 0
123; GENERIC: call i16 @llvm.cttz.i16(i16 %A, i1 true)
124entry:
125  %tobool = icmp eq i16 %A, 0
126  br i1 %tobool, label %cond.end, label %cond.true
127
128cond.true:                                        ; preds = %entry
129  %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
130  br label %cond.end
131
132cond.end:                                         ; preds = %entry, %cond.true
133  %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
134  ret i16 %cond
135}
136
137
138define i64 @test1c(i64 %A) {
139; ALL-LABEL: @test1c(
140; ALL: icmp eq i64 %A, 0
141; ALL: call i64 @llvm.ctlz.i64(i64 %A, i1 true)
142entry:
143  %tobool = icmp eq i64 %A, 0
144  br i1 %tobool, label %cond.end, label %cond.true
145
146cond.true:                                        ; preds = %entry
147  %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
148  br label %cond.end
149
150cond.end:                                         ; preds = %entry, %cond.true
151  %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ]
152  ret i64 %cond
153}
154
155define i32 @test2c(i32 %A) {
156; ALL-LABEL: @test2c(
157; ALL: icmp eq i32 %A, 0
158; ALL: call i32 @llvm.ctlz.i32(i32 %A, i1 true)
159entry:
160  %tobool = icmp eq i32 %A, 0
161  br i1 %tobool, label %cond.end, label %cond.true
162
163cond.true:                                        ; preds = %entry
164  %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
165  br label %cond.end
166
167cond.end:                                         ; preds = %entry, %cond.true
168  %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ]
169  ret i32 %cond
170}
171
172
173define signext i16 @test3c(i16 signext %A) {
174; ALL-LABEL: @test3c(
175; ALL: icmp eq i16 %A, 0
176; ALL: call i16 @llvm.ctlz.i16(i16 %A, i1 true)
177entry:
178  %tobool = icmp eq i16 %A, 0
179  br i1 %tobool, label %cond.end, label %cond.true
180
181cond.true:                                        ; preds = %entry
182  %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
183  br label %cond.end
184
185cond.end:                                         ; preds = %entry, %cond.true
186  %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ]
187  ret i16 %cond
188}
189
190
191define i64 @test1d(i64 %A) {
192; ALL-LABEL: @test1d(
193; ALL: icmp eq i64 %A, 0
194; ALL: call i64 @llvm.cttz.i64(i64 %A, i1 true)
195entry:
196  %tobool = icmp eq i64 %A, 0
197  br i1 %tobool, label %cond.end, label %cond.true
198
199cond.true:                                        ; preds = %entry
200  %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
201  br label %cond.end
202
203cond.end:                                         ; preds = %entry, %cond.true
204  %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ]
205  ret i64 %cond
206}
207
208
209define i32 @test2d(i32 %A) {
210; ALL-LABEL: @test2d(
211; ALL: icmp eq i32 %A, 0
212; ALL: call i32 @llvm.cttz.i32(i32 %A, i1 true)
213entry:
214  %tobool = icmp eq i32 %A, 0
215  br i1 %tobool, label %cond.end, label %cond.true
216
217cond.true:                                        ; preds = %entry
218  %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
219  br label %cond.end
220
221cond.end:                                         ; preds = %entry, %cond.true
222  %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ]
223  ret i32 %cond
224}
225
226
227define signext i16 @test3d(i16 signext %A) {
228; ALL-LABEL: @test3d(
229; ALL: icmp eq i16 %A, 0
230; ALL: call i16 @llvm.cttz.i16(i16 %A, i1 true)
231entry:
232  %tobool = icmp eq i16 %A, 0
233  br i1 %tobool, label %cond.end, label %cond.true
234
235cond.true:                                        ; preds = %entry
236  %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
237  br label %cond.end
238
239cond.end:                                         ; preds = %entry, %cond.true
240  %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ]
241  ret i16 %cond
242}
243
244; The following tests verify that calls to cttz/ctlz are speculated even if
245; basic block %cond.true has an extra zero extend/truncate which is "free"
246; for the target.
247
248define i64 @test1e(i32 %x) {
249; ALL-LABEL: @test1e(
250; LZCNT: icmp eq i32 %x, 0
251; LZCNT: call i32 @llvm.cttz.i32(i32 %x, i1 true)
252; BMI: call i32 @llvm.cttz.i32(i32 %x, i1 false)
253; GENERIC: icmp eq i32 %x, 0
254; GENERIC: call i32 @llvm.cttz.i32(i32 %x, i1 true)
255entry:
256  %tobool = icmp eq i32 %x, 0
257  br i1 %tobool, label %cond.end, label %cond.true
258
259cond.true:                                        ; preds = %entry
260  %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
261  %phitmp2 = zext i32 %0 to i64
262  br label %cond.end
263
264cond.end:                                         ; preds = %entry, %cond.true
265  %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
266  ret i64 %cond
267}
268
269define i32 @test2e(i64 %x) {
270; ALL-LABEL: @test2e(
271; LZCNT: icmp eq i64 %x, 0
272; LZCNT: call i64 @llvm.cttz.i64(i64 %x, i1 true)
273; BMI: call i64 @llvm.cttz.i64(i64 %x, i1 false)
274; GENERIC: icmp eq i64 %x, 0
275; GENERIC: call i64 @llvm.cttz.i64(i64 %x, i1 true)
276entry:
277  %tobool = icmp eq i64 %x, 0
278  br i1 %tobool, label %cond.end, label %cond.true
279
280cond.true:                                        ; preds = %entry
281  %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
282  %cast = trunc i64 %0 to i32
283  br label %cond.end
284
285cond.end:                                         ; preds = %entry, %cond.true
286  %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
287  ret i32 %cond
288}
289
290define i64 @test3e(i32 %x) {
291; ALL-LABEL: @test3e(
292; BMI: icmp eq i32 %x, 0
293; BMI: call i32 @llvm.ctlz.i32(i32 %x, i1 true)
294; LZCNT: call i32 @llvm.ctlz.i32(i32 %x, i1 false)
295; GENERIC: icmp eq i32 %x, 0
296; GENERIC: call i32 @llvm.ctlz.i32(i32 %x, i1 true)
297entry:
298  %tobool = icmp eq i32 %x, 0
299  br i1 %tobool, label %cond.end, label %cond.true
300
301cond.true:                                        ; preds = %entry
302  %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
303  %phitmp2 = zext i32 %0 to i64
304  br label %cond.end
305
306cond.end:                                         ; preds = %entry, %cond.true
307  %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
308  ret i64 %cond
309}
310
311define i32 @test4e(i64 %x) {
312; ALL-LABEL: @test4e(
313; BMI: icmp eq i64 %x, 0
314; BMI: call i64 @llvm.ctlz.i64(i64 %x, i1 true)
315; LZCNT: call i64 @llvm.ctlz.i64(i64 %x, i1 false)
316; GENERIC: icmp eq i64 %x, 0
317; GENERIC: call i64 @llvm.ctlz.i64(i64 %x, i1 true)
318entry:
319  %tobool = icmp eq i64 %x, 0
320  br i1 %tobool, label %cond.end, label %cond.true
321
322cond.true:                                        ; preds = %entry
323  %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
324  %cast = trunc i64 %0 to i32
325  br label %cond.end
326
327cond.end:                                         ; preds = %entry, %cond.true
328  %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
329  ret i32 %cond
330}
331
332define i16 @test5e(i64 %x) {
333; ALL-LABEL: @test5e(
334; BMI: icmp eq i64 %x, 0
335; BMI: call i64 @llvm.ctlz.i64(i64 %x, i1 true)
336; LZCNT: call i64 @llvm.ctlz.i64(i64 %x, i1 false)
337; GENERIC: icmp eq i64 %x, 0
338; GENERIC: call i64 @llvm.ctlz.i64(i64 %x, i1 true)
339entry:
340  %tobool = icmp eq i64 %x, 0
341  br i1 %tobool, label %cond.end, label %cond.true
342
343cond.true:                                        ; preds = %entry
344  %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
345  %cast = trunc i64 %0 to i16
346  br label %cond.end
347
348cond.end:                                         ; preds = %entry, %cond.true
349  %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
350  ret i16 %cond
351}
352
353define i16 @test6e(i32 %x) {
354; ALL-LABEL: @test6e(
355; BMI: icmp eq i32 %x, 0
356; BMI: call i32 @llvm.ctlz.i32(i32 %x, i1 true)
357; LZCNT: call i32 @llvm.ctlz.i32(i32 %x, i1 false)
358; GENERIC: icmp eq i32 %x, 0
359; GENERIC: call i32 @llvm.ctlz.i32(i32 %x, i1 true)
360entry:
361  %tobool = icmp eq i32 %x, 0
362  br i1 %tobool, label %cond.end, label %cond.true
363
364cond.true:                                        ; preds = %entry
365  %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
366  %cast = trunc i32 %0 to i16
367  br label %cond.end
368
369cond.end:                                         ; preds = %entry, %cond.true
370  %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
371  ret i16 %cond
372}
373
374define i16 @test7e(i64 %x) {
375; ALL-LABEL: @test7e(
376; LZCNT: icmp eq i64 %x, 0
377; LZCNT: call i64 @llvm.cttz.i64(i64 %x, i1 true)
378; BMI: call i64 @llvm.cttz.i64(i64 %x, i1 false)
379; GENERIC: icmp eq i64 %x, 0
380; GENERIC: call i64 @llvm.cttz.i64(i64 %x, i1 true)
381entry:
382  %tobool = icmp eq i64 %x, 0
383  br i1 %tobool, label %cond.end, label %cond.true
384
385cond.true:                                        ; preds = %entry
386  %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
387  %cast = trunc i64 %0 to i16
388  br label %cond.end
389
390cond.end:                                         ; preds = %entry, %cond.true
391  %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
392  ret i16 %cond
393}
394
395define i16 @test8e(i32 %x) {
396; ALL-LABEL: @test8e(
397; LZCNT: icmp eq i32 %x, 0
398; LZCNT: call i32 @llvm.cttz.i32(i32 %x, i1 true)
399; BMI: call i32 @llvm.cttz.i32(i32 %x, i1 false)
400; GENERIC: icmp eq i32 %x, 0
401; GENERIC: call i32 @llvm.cttz.i32(i32 %x, i1 true)
402entry:
403  %tobool = icmp eq i32 %x, 0
404  br i1 %tobool, label %cond.end, label %cond.true
405
406cond.true:                                        ; preds = %entry
407  %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
408  %cast = trunc i32 %0 to i16
409  br label %cond.end
410
411cond.end:                                         ; preds = %entry, %cond.true
412  %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
413  ret i16 %cond
414}
415
416
417declare i64 @llvm.ctlz.i64(i64, i1)
418declare i32 @llvm.ctlz.i32(i32, i1)
419declare i16 @llvm.ctlz.i16(i16, i1)
420declare i64 @llvm.cttz.i64(i64, i1)
421declare i32 @llvm.cttz.i32(i32, i1)
422declare i16 @llvm.cttz.i16(i16, i1)
423