1; RUN: opt -instcombine -S < %s | FileCheck %s
2
3; This test is to verify that the instruction combiner is able to fold
4; a cttz/ctlz followed by a icmp + select into a single cttz/ctlz with
5; the 'is_zero_undef' flag cleared.
6
7define i16 @test1(i16 %x) {
8; CHECK-LABEL: @test1(
9; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
10; CHECK-NEXT: ret i16 [[VAR]]
11entry:
12  %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
13  %tobool = icmp ne i16 %x, 0
14  %cond = select i1 %tobool, i16 %0, i16 16
15  ret i16 %cond
16}
17
18define i32 @test2(i32 %x) {
19; CHECK-LABEL: @test2(
20; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
21; CHECK-NEXT: ret i32 [[VAR]]
22entry:
23  %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
24  %tobool = icmp ne i32 %x, 0
25  %cond = select i1 %tobool, i32 %0, i32 32
26  ret i32 %cond
27}
28
29define i64 @test3(i64 %x) {
30; CHECK-LABEL: @test3(
31; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
32; CHECK-NEXT: ret i64 [[VAR]]
33entry:
34  %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
35  %tobool = icmp ne i64 %x, 0
36  %cond = select i1 %tobool, i64 %0, i64 64
37  ret i64 %cond
38}
39
40define i16 @test4(i16 %x) {
41; CHECK-LABEL: @test4(
42; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
43; CHECK-NEXT: ret i16 [[VAR]]
44entry:
45  %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
46  %tobool = icmp eq i16 %x, 0
47  %cond = select i1 %tobool, i16 16, i16 %0
48  ret i16 %cond
49}
50
51define i32 @test5(i32 %x) {
52; CHECK-LABEL: @test5(
53; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
54; CHECK-NEXT: ret i32 [[VAR]]
55entry:
56  %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
57  %tobool = icmp eq i32 %x, 0
58  %cond = select i1 %tobool, i32 32, i32 %0
59  ret i32 %cond
60}
61
62define i64 @test6(i64 %x) {
63; CHECK-LABEL: @test6(
64; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
65; CHECK-NEXT: ret i64 [[VAR]]
66entry:
67  %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
68  %tobool = icmp eq i64 %x, 0
69  %cond = select i1 %tobool, i64 64, i64 %0
70  ret i64 %cond
71}
72
73define i16 @test1b(i16 %x) {
74; CHECK-LABEL: @test1b(
75; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false)
76; CHECK-NEXT: ret i16 [[VAR]]
77entry:
78  %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
79  %tobool = icmp ne i16 %x, 0
80  %cond = select i1 %tobool, i16 %0, i16 16
81  ret i16 %cond
82}
83
84define i32 @test2b(i32 %x) {
85; CHECK-LABEL: @test2b(
86; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
87; CHECK-NEXT: ret i32 [[VAR]]
88entry:
89  %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
90  %tobool = icmp ne i32 %x, 0
91  %cond = select i1 %tobool, i32 %0, i32 32
92  ret i32 %cond
93}
94
95define i64 @test3b(i64 %x) {
96; CHECK-LABEL: @test3b(
97; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
98; CHECK-NEXT: ret i64 [[VAR]]
99entry:
100  %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
101  %tobool = icmp ne i64 %x, 0
102  %cond = select i1 %tobool, i64 %0, i64 64
103  ret i64 %cond
104}
105
106define i16 @test4b(i16 %x) {
107; CHECK-LABEL: @test4b(
108; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false)
109; CHECK-NEXT: ret i16 [[VAR]]
110entry:
111  %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
112  %tobool = icmp eq i16 %x, 0
113  %cond = select i1 %tobool, i16 16, i16 %0
114  ret i16 %cond
115}
116
117define i32 @test5b(i32 %x) {
118; CHECK-LABEL: @test5b(
119; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
120; CHECK-NEXT: ret i32 [[VAR]]
121entry:
122  %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
123  %tobool = icmp eq i32 %x, 0
124  %cond = select i1 %tobool, i32 32, i32 %0
125  ret i32 %cond
126}
127
128define i64 @test6b(i64 %x) {
129; CHECK-LABEL: @test6b(
130; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
131; CHECK-NEXT: ret i64 [[VAR]]
132entry:
133  %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
134  %tobool = icmp eq i64 %x, 0
135  %cond = select i1 %tobool, i64 64, i64 %0
136  ret i64 %cond
137}
138
139define i32 @test1c(i16 %x) {
140; CHECK-LABEL: @test1c(
141; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false)
142; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i32
143; CHECK-NEXT: ret i32 [[VAR2]]
144entry:
145  %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
146  %cast2 = zext i16 %0 to i32
147  %tobool = icmp ne i16 %x, 0
148  %cond = select i1 %tobool, i32 %cast2, i32 16
149  ret i32 %cond
150}
151
152define i64 @test2c(i16 %x) {
153; CHECK-LABEL: @test2c(
154; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false)
155; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i64
156; CHECK-NEXT: ret i64 [[VAR2]]
157entry:
158  %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
159  %conv = zext i16 %0 to i64
160  %tobool = icmp ne i16 %x, 0
161  %cond = select i1 %tobool, i64 %conv, i64 16
162  ret i64 %cond
163}
164
165define i64 @test3c(i32 %x) {
166; CHECK-LABEL: @test3c(
167; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
168; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64
169; CHECK-NEXT: ret i64 [[VAR2]]
170entry:
171  %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
172  %conv = zext i32 %0 to i64
173  %tobool = icmp ne i32 %x, 0
174  %cond = select i1 %tobool, i64 %conv, i64 32
175  ret i64 %cond
176}
177
178define i32 @test4c(i16 %x) {
179; CHECK-LABEL: @test4c(
180; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
181; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i32
182; CHECK-NEXT: ret i32 [[VAR2]]
183entry:
184  %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
185  %cast = zext i16 %0 to i32
186  %tobool = icmp ne i16 %x, 0
187  %cond = select i1 %tobool, i32 %cast, i32 16
188  ret i32 %cond
189}
190
191define i64 @test5c(i16 %x) {
192; CHECK-LABEL: @test5c(
193; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
194; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i64
195; CHECK-NEXT: ret i64 [[VAR2]]
196entry:
197  %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
198  %cast = zext i16 %0 to i64
199  %tobool = icmp ne i16 %x, 0
200  %cond = select i1 %tobool, i64 %cast, i64 16
201  ret i64 %cond
202}
203
204define i64 @test6c(i32 %x) {
205; CHECK-LABEL: @test6c(
206; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
207; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64
208; CHECK-NEXT: ret i64 [[VAR2]]
209entry:
210  %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
211  %cast = zext i32 %0 to i64
212  %tobool = icmp ne i32 %x, 0
213  %cond = select i1 %tobool, i64 %cast, i64 32
214  ret i64 %cond
215}
216
217define i16 @test1d(i64 %x) {
218; CHECK-LABEL: @test1d(
219; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
220; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i16
221; CHECK-NEXT: ret i16 [[VAR2]]
222entry:
223  %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
224  %conv = trunc i64 %0 to i16
225  %tobool = icmp ne i64 %x, 0
226  %cond = select i1 %tobool, i16 %conv, i16 64
227  ret i16 %cond
228}
229
230define i32 @test2d(i64 %x) {
231; CHECK-LABEL: @test2d(
232; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
233; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i32
234; CHECK-NEXT: ret i32 [[VAR2]]
235entry:
236  %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
237  %cast = trunc i64 %0 to i32
238  %tobool = icmp ne i64 %x, 0
239  %cond = select i1 %tobool, i32 %cast, i32 64
240  ret i32 %cond
241}
242
243define i16 @test3d(i32 %x) {
244; CHECK-LABEL: @test3d(
245; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
246; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16
247; CHECK-NEXT: ret i16 [[VAR2]]
248entry:
249  %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
250  %cast = trunc i32 %0 to i16
251  %tobool = icmp ne i32 %x, 0
252  %cond = select i1 %tobool, i16 %cast, i16 32
253  ret i16 %cond
254}
255
256define i16 @test4d(i64 %x) {
257; CHECK-LABEL: @test4d(
258; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
259; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i16
260; CHECK-NEXT: ret i16 [[VAR2]]
261entry:
262  %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
263  %cast = trunc i64 %0 to i16
264  %tobool = icmp ne i64 %x, 0
265  %cond = select i1 %tobool, i16 %cast, i16 64
266  ret i16 %cond
267}
268
269define i32 @test5d(i64 %x) {
270; CHECK-LABEL: @test5d(
271; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
272; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i32
273; CHECK-NEXT: ret i32 [[VAR2]]
274entry:
275  %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
276  %cast = trunc i64 %0 to i32
277  %tobool = icmp ne i64 %x, 0
278  %cond = select i1 %tobool, i32 %cast, i32 64
279  ret i32 %cond
280}
281
282define i16 @test6d(i32 %x) {
283; CHECK-LABEL: @test6d(
284; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
285; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16
286; CHECK-NEXT: ret i16 [[VAR2]]
287entry:
288  %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
289  %cast = trunc i32 %0 to i16
290  %tobool = icmp ne i32 %x, 0
291  %cond = select i1 %tobool, i16 %cast, i16 32
292  ret i16 %cond
293}
294
295define i64 @select_bug1(i32 %x) {
296; CHECK-LABEL: @select_bug1(
297; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
298; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64
299; CHECK-NEXT: ret i64 [[VAR2]]
300entry:
301  %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
302  %conv = zext i32 %0 to i64
303  %tobool = icmp ne i32 %x, 0
304  %cond = select i1 %tobool, i64 %conv, i64 32
305  ret i64 %cond
306}
307
308define i16 @select_bug2(i32 %x) {
309; CHECK-LABEL: @select_bug2(
310; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
311; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16
312; CHECK-NEXT: ret i16 [[VAR2]]
313entry:
314  %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
315  %conv = trunc i32 %0 to i16
316  %tobool = icmp ne i32 %x, 0
317  %cond = select i1 %tobool, i16 %conv, i16 32
318  ret i16 %cond
319}
320
321define i128 @test7(i128 %x) {
322; CHECK-LABEL: @test7(
323; CHECK-NEXT:    [[TMP1:%.*]] = tail call i128 @llvm.ctlz.i128(i128 [[X:%.*]], i1 false), !range !3
324; CHECK-NEXT:    ret i128 [[TMP1]]
325;
326  %1 = tail call i128 @llvm.ctlz.i128(i128 %x, i1 true)
327  %tobool = icmp ne i128 %x, 0
328  %cond = select i1 %tobool, i128 %1, i128 128
329  ret i128 %cond
330}
331
332define i128 @test8(i128 %x) {
333; CHECK-LABEL: @test8(
334; CHECK-NEXT:    [[TMP1:%.*]] = tail call i128 @llvm.cttz.i128(i128 [[X:%.*]], i1 false), !range !3
335; CHECK-NEXT:    ret i128 [[TMP1]]
336;
337  %1 = tail call i128 @llvm.cttz.i128(i128 %x, i1 true)
338  %tobool = icmp ne i128 %x, 0
339  %cond = select i1 %tobool, i128 %1, i128 128
340  ret i128 %cond
341}
342
343declare i16 @llvm.ctlz.i16(i16, i1)
344declare i32 @llvm.ctlz.i32(i32, i1)
345declare i64 @llvm.ctlz.i64(i64, i1)
346declare i128 @llvm.ctlz.i128(i128, i1)
347declare i16 @llvm.cttz.i16(i16, i1)
348declare i32 @llvm.cttz.i32(i32, i1)
349declare i64 @llvm.cttz.i64(i64, i1)
350declare i128 @llvm.cttz.i128(i128, i1)
351