1 ; RUN: opt -instcombine -S < %s | FileCheck %s
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.
7 define i16 @test1(i16 %x) {
9 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
10 ; CHECK-NEXT: ret i16 [[VAR]]
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
18 define 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]]
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
29 define 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]]
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
40 define 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]]
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
51 define 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]]
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
62 define 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]]
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
73 define 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]]
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
84 define 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]]
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
95 define 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]]
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
106 define 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]]
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
117 define 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]]
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
128 define 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]]
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
139 define 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]]
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
152 define 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]]
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
165 define 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]]
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
178 define 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]]
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
191 define 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]]
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
204 define 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]]
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
217 define 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]]
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
230 define 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]]
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
243 define 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]]
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
256 define 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]]
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
269 define 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]]
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
282 define 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]]
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
295 define 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]]
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
308 define 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]]
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
322 declare i16 @llvm.ctlz.i16(i16, i1)
323 declare i32 @llvm.ctlz.i32(i32, i1)
324 declare i64 @llvm.ctlz.i64(i64, i1)
325 declare i16 @llvm.cttz.i16(i16, i1)
326 declare i32 @llvm.cttz.i32(i32, i1)
327 declare i64 @llvm.cttz.i64(i64, i1)