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
6 define i64 @test1(i64 %A) {
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)
15 %tobool = icmp eq i64 %A, 0
16 br i1 %tobool, label %cond.end, label %cond.true
18 cond.true: ; preds = %entry
19 %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
22 cond.end: ; preds = %entry, %cond.true
23 %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
28 define i32 @test2(i32 %A) {
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)
37 %tobool = icmp eq i32 %A, 0
38 br i1 %tobool, label %cond.end, label %cond.true
40 cond.true: ; preds = %entry
41 %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
44 cond.end: ; preds = %entry, %cond.true
45 %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
50 define signext i16 @test3(i16 signext %A) {
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)
59 %tobool = icmp eq i16 %A, 0
60 br i1 %tobool, label %cond.end, label %cond.true
62 cond.true: ; preds = %entry
63 %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
66 cond.end: ; preds = %entry, %cond.true
67 %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
72 define i64 @test1b(i64 %A) {
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)
81 %tobool = icmp eq i64 %A, 0
82 br i1 %tobool, label %cond.end, label %cond.true
84 cond.true: ; preds = %entry
85 %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
88 cond.end: ; preds = %entry, %cond.true
89 %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
94 define i32 @test2b(i32 %A) {
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)
103 %tobool = icmp eq i32 %A, 0
104 br i1 %tobool, label %cond.end, label %cond.true
106 cond.true: ; preds = %entry
107 %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
110 cond.end: ; preds = %entry, %cond.true
111 %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
116 define 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)
125 %tobool = icmp eq i16 %A, 0
126 br i1 %tobool, label %cond.end, label %cond.true
128 cond.true: ; preds = %entry
129 %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
132 cond.end: ; preds = %entry, %cond.true
133 %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
138 define 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)
143 %tobool = icmp eq i64 %A, 0
144 br i1 %tobool, label %cond.end, label %cond.true
146 cond.true: ; preds = %entry
147 %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
150 cond.end: ; preds = %entry, %cond.true
151 %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ]
155 define 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)
160 %tobool = icmp eq i32 %A, 0
161 br i1 %tobool, label %cond.end, label %cond.true
163 cond.true: ; preds = %entry
164 %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
167 cond.end: ; preds = %entry, %cond.true
168 %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ]
173 define 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)
178 %tobool = icmp eq i16 %A, 0
179 br i1 %tobool, label %cond.end, label %cond.true
181 cond.true: ; preds = %entry
182 %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
185 cond.end: ; preds = %entry, %cond.true
186 %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ]
191 define 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)
196 %tobool = icmp eq i64 %A, 0
197 br i1 %tobool, label %cond.end, label %cond.true
199 cond.true: ; preds = %entry
200 %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
203 cond.end: ; preds = %entry, %cond.true
204 %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ]
209 define 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)
214 %tobool = icmp eq i32 %A, 0
215 br i1 %tobool, label %cond.end, label %cond.true
217 cond.true: ; preds = %entry
218 %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
221 cond.end: ; preds = %entry, %cond.true
222 %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ]
227 define 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)
232 %tobool = icmp eq i16 %A, 0
233 br i1 %tobool, label %cond.end, label %cond.true
235 cond.true: ; preds = %entry
236 %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
239 cond.end: ; preds = %entry, %cond.true
240 %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ]
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"
248 define 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)
256 %tobool = icmp eq i32 %x, 0
257 br i1 %tobool, label %cond.end, label %cond.true
259 cond.true: ; preds = %entry
260 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
261 %phitmp2 = zext i32 %0 to i64
264 cond.end: ; preds = %entry, %cond.true
265 %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
269 define 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)
277 %tobool = icmp eq i64 %x, 0
278 br i1 %tobool, label %cond.end, label %cond.true
280 cond.true: ; preds = %entry
281 %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
282 %cast = trunc i64 %0 to i32
285 cond.end: ; preds = %entry, %cond.true
286 %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
290 define 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)
298 %tobool = icmp eq i32 %x, 0
299 br i1 %tobool, label %cond.end, label %cond.true
301 cond.true: ; preds = %entry
302 %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
303 %phitmp2 = zext i32 %0 to i64
306 cond.end: ; preds = %entry, %cond.true
307 %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
311 define 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)
319 %tobool = icmp eq i64 %x, 0
320 br i1 %tobool, label %cond.end, label %cond.true
322 cond.true: ; preds = %entry
323 %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
324 %cast = trunc i64 %0 to i32
327 cond.end: ; preds = %entry, %cond.true
328 %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
332 define 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)
340 %tobool = icmp eq i64 %x, 0
341 br i1 %tobool, label %cond.end, label %cond.true
343 cond.true: ; preds = %entry
344 %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
345 %cast = trunc i64 %0 to i16
348 cond.end: ; preds = %entry, %cond.true
349 %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
353 define 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)
361 %tobool = icmp eq i32 %x, 0
362 br i1 %tobool, label %cond.end, label %cond.true
364 cond.true: ; preds = %entry
365 %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
366 %cast = trunc i32 %0 to i16
369 cond.end: ; preds = %entry, %cond.true
370 %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
374 define 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)
382 %tobool = icmp eq i64 %x, 0
383 br i1 %tobool, label %cond.end, label %cond.true
385 cond.true: ; preds = %entry
386 %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
387 %cast = trunc i64 %0 to i16
390 cond.end: ; preds = %entry, %cond.true
391 %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
395 define 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)
403 %tobool = icmp eq i32 %x, 0
404 br i1 %tobool, label %cond.end, label %cond.true
406 cond.true: ; preds = %entry
407 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
408 %cast = trunc i32 %0 to i16
411 cond.end: ; preds = %entry, %cond.true
412 %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
417 declare i64 @llvm.ctlz.i64(i64, i1)
418 declare i32 @llvm.ctlz.i32(i32, i1)
419 declare i16 @llvm.ctlz.i16(i16, i1)
420 declare i64 @llvm.cttz.i64(i64, i1)
421 declare i32 @llvm.cttz.i32(i32, i1)
422 declare i16 @llvm.cttz.i16(i16, i1)