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