• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI
2; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT
3; RUN: opt -S -simplifycfg -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; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
9; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
10; LZCNT-NEXT: select i1 [[COND]], i64 64, i64 [[CTLZ]]
11; BMI-NOT: select
12; GENERIC-NOT: select
13; ALL: ret
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
27define i32 @test2(i32 %A) {
28; ALL-LABEL: @test2(
29; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
30; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
31; LZCNT-NEXT: select i1 [[COND]], i32 32, i32 [[CTLZ]]
32; BMI-NOT: select
33; GENERIC-NOT: select
34; ALL: ret
35entry:
36  %tobool = icmp eq i32 %A, 0
37  br i1 %tobool, label %cond.end, label %cond.true
38
39cond.true:                                        ; preds = %entry
40  %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
41  br label %cond.end
42
43cond.end:                                         ; preds = %entry, %cond.true
44  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
45  ret i32 %cond
46}
47
48
49define signext i16 @test3(i16 signext %A) {
50; ALL-LABEL: @test3(
51; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
52; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
53; LZCNT-NEXT: select i1 [[COND]], i16 16, i16 [[CTLZ]]
54; BMI-NOT: select
55; GENERIC-NOT: select
56; ALL: ret
57entry:
58  %tobool = icmp eq i16 %A, 0
59  br i1 %tobool, label %cond.end, label %cond.true
60
61cond.true:                                        ; preds = %entry
62  %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
63  br label %cond.end
64
65cond.end:                                         ; preds = %entry, %cond.true
66  %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
67  ret i16 %cond
68}
69
70
71define i64 @test1b(i64 %A) {
72; ALL-LABEL: @test1b(
73; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
74; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
75; BMI-NEXT: select i1 [[COND]], i64 64, i64 [[CTTZ]]
76; LZCNT-NOT: select
77; GENERIC-NOT: select
78; ALL: ret
79entry:
80  %tobool = icmp eq i64 %A, 0
81  br i1 %tobool, label %cond.end, label %cond.true
82
83cond.true:                                        ; preds = %entry
84  %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
85  br label %cond.end
86
87cond.end:                                         ; preds = %entry, %cond.true
88  %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
89  ret i64 %cond
90}
91
92
93define i32 @test2b(i32 %A) {
94; ALL-LABEL: @test2b(
95; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
96; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
97; BMI-NEXT: select i1 [[COND]], i32 32, i32 [[CTTZ]]
98; LZCNT-NOT: select
99; GENERIC-NOT: select
100; ALL: ret
101entry:
102  %tobool = icmp eq i32 %A, 0
103  br i1 %tobool, label %cond.end, label %cond.true
104
105cond.true:                                        ; preds = %entry
106  %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
107  br label %cond.end
108
109cond.end:                                         ; preds = %entry, %cond.true
110  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
111  ret i32 %cond
112}
113
114
115define signext i16 @test3b(i16 signext %A) {
116; ALL-LABEL: @test3b(
117; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
118; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
119; BMI-NEXT: select i1 [[COND]], i16 16, i16 [[CTTZ]]
120; LZCNT-NOT: select
121; GENERIC-NOT: select
122; ALL: ret
123entry:
124  %tobool = icmp eq i16 %A, 0
125  br i1 %tobool, label %cond.end, label %cond.true
126
127cond.true:                                        ; preds = %entry
128  %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
129  br label %cond.end
130
131cond.end:                                         ; preds = %entry, %cond.true
132  %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
133  ret i16 %cond
134}
135
136; The following tests verify that calls to cttz/ctlz are speculated even if
137; basic block %cond.true has an extra zero extend/truncate which is "free"
138; for the target.
139
140define i64 @test1e(i32 %x) {
141; ALL-LABEL: @test1e(
142; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
143; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
144; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTTZ]] to i64
145; BMI-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]]
146; LZCNT-NOT: select
147; GENERIC-NOT: select
148; ALL: ret
149entry:
150  %tobool = icmp eq i32 %x, 0
151  br i1 %tobool, label %cond.end, label %cond.true
152
153cond.true:                                        ; preds = %entry
154  %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
155  %phitmp2 = zext i32 %0 to i64
156  br label %cond.end
157
158cond.end:                                         ; preds = %entry, %cond.true
159  %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
160  ret i64 %cond
161}
162
163define i32 @test2e(i64 %x) {
164; ALL-LABEL: @test2e(
165; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
166; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
167; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i32
168; BMI-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]]
169; LZCNT-NOT: select
170; GENERIC-NOT: select
171; ALL: ret
172entry:
173  %tobool = icmp eq i64 %x, 0
174  br i1 %tobool, label %cond.end, label %cond.true
175
176cond.true:                                        ; preds = %entry
177  %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
178  %cast = trunc i64 %0 to i32
179  br label %cond.end
180
181cond.end:                                         ; preds = %entry, %cond.true
182  %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
183  ret i32 %cond
184}
185
186define i64 @test3e(i32 %x) {
187; ALL-LABEL: @test3e(
188; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
189; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
190; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTLZ]] to i64
191; LZCNT-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]]
192; BMI-NOT: select
193; GENERIC-NOT: select
194; ALL: ret
195entry:
196  %tobool = icmp eq i32 %x, 0
197  br i1 %tobool, label %cond.end, label %cond.true
198
199cond.true:                                        ; preds = %entry
200  %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
201  %phitmp2 = zext i32 %0 to i64
202  br label %cond.end
203
204cond.end:                                         ; preds = %entry, %cond.true
205  %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
206  ret i64 %cond
207}
208
209define i32 @test4e(i64 %x) {
210; ALL-LABEL: @test4e(
211; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
212; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
213; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i32
214; LZCNT-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]]
215; BMI-NOT: select
216; GENERIC-NOT: select
217; ALL: ret
218entry:
219  %tobool = icmp eq i64 %x, 0
220  br i1 %tobool, label %cond.end, label %cond.true
221
222cond.true:                                        ; preds = %entry
223  %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
224  %cast = trunc i64 %0 to i32
225  br label %cond.end
226
227cond.end:                                         ; preds = %entry, %cond.true
228  %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
229  ret i32 %cond
230}
231
232define i16 @test5e(i64 %x) {
233; ALL-LABEL: @test5e(
234; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
235; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
236; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i16
237; LZCNT-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]]
238; BMI-NOT: select
239; GENERIC-NOT: select
240; ALL: ret
241entry:
242  %tobool = icmp eq i64 %x, 0
243  br i1 %tobool, label %cond.end, label %cond.true
244
245cond.true:                                        ; preds = %entry
246  %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
247  %cast = trunc i64 %0 to i16
248  br label %cond.end
249
250cond.end:                                         ; preds = %entry, %cond.true
251  %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
252  ret i16 %cond
253}
254
255define i16 @test6e(i32 %x) {
256; ALL-LABEL: @test6e(
257; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
258; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
259; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTLZ]] to i16
260; LZCNT-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]]
261; BMI-NOT: select
262; GENERIC-NOT: select
263; ALL: ret
264entry:
265  %tobool = icmp eq i32 %x, 0
266  br i1 %tobool, label %cond.end, label %cond.true
267
268cond.true:                                        ; preds = %entry
269  %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
270  %cast = trunc i32 %0 to i16
271  br label %cond.end
272
273cond.end:                                         ; preds = %entry, %cond.true
274  %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
275  ret i16 %cond
276}
277
278define i16 @test7e(i64 %x) {
279; ALL-LABEL: @test7e(
280; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
281; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
282; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i16
283; BMI-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]]
284; LZCNT-NOT: select
285; GENERIC-NOT: select
286; ALL: ret
287entry:
288  %tobool = icmp eq i64 %x, 0
289  br i1 %tobool, label %cond.end, label %cond.true
290
291cond.true:                                        ; preds = %entry
292  %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
293  %cast = trunc i64 %0 to i16
294  br label %cond.end
295
296cond.end:                                         ; preds = %entry, %cond.true
297  %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
298  ret i16 %cond
299}
300
301define i16 @test8e(i32 %x) {
302; ALL-LABEL: @test8e(
303; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
304; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
305; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTTZ]] to i16
306; BMI-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]]
307; LZCNT-NOT: select
308; GENERIC-NOT: select
309; ALL: ret
310entry:
311  %tobool = icmp eq i32 %x, 0
312  br i1 %tobool, label %cond.end, label %cond.true
313
314cond.true:                                        ; preds = %entry
315  %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
316  %cast = trunc i32 %0 to i16
317  br label %cond.end
318
319cond.end:                                         ; preds = %entry, %cond.true
320  %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
321  ret i16 %cond
322}
323
324
325declare i64 @llvm.ctlz.i64(i64, i1)
326declare i32 @llvm.ctlz.i32(i32, i1)
327declare i16 @llvm.ctlz.i16(i16, i1)
328declare i64 @llvm.cttz.i64(i64, i1)
329declare i32 @llvm.cttz.i32(i32, i1)
330declare i16 @llvm.cttz.i16(i16, i1)
331