1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -instcombine -S < %s | FileCheck %s
5 declare i32 @llvm.cttz.i32(i32, i1 immarg)
6 declare i32 @llvm.ctlz.i32(i32, i1 immarg)
7 declare i64 @llvm.cttz.i64(i64, i1 immarg)
8 declare i64 @llvm.ctlz.i64(i64, i1 immarg)
10 declare <2 x i32> @llvm.ctlz.v2i32(<2 x i32>, i1)
11 declare <2 x i32> @llvm.cttz.v2i32(<2 x i32>, i1)
14 declare void @use(i32)
15 declare void @use2(i1)
17 define i32 @select_clz_to_ctz(i32 %a) {
18 ; CHECK-LABEL: @select_clz_to_ctz(
19 ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.cttz.i32(i32 [[A:%.*]], i1 true), !range !0
20 ; CHECK-NEXT: ret i32 [[COND]]
23 %and = and i32 %sub, %a
24 %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true)
25 %tobool = icmp eq i32 %a, 0
26 %sub1 = xor i32 %lz, 31
27 %cond = select i1 %tobool, i32 %lz, i32 %sub1
31 define i32 @select_clz_to_ctz_preserve_flag(i32 %a) {
32 ; CHECK-LABEL: @select_clz_to_ctz_preserve_flag(
33 ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.cttz.i32(i32 [[A:%.*]], i1 false), !range !0
34 ; CHECK-NEXT: ret i32 [[COND]]
37 %and = and i32 %sub, %a
38 %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 false)
39 %tobool = icmp eq i32 %a, 0
40 %sub1 = xor i32 %lz, 31
41 %cond = select i1 %tobool, i32 %lz, i32 %sub1
45 define <2 x i32> @select_clz_to_ctz_vec(<2 x i32> %a) {
46 ; CHECK-LABEL: @select_clz_to_ctz_vec(
47 ; CHECK-NEXT: [[COND:%.*]] = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[A:%.*]], i1 true)
48 ; CHECK-NEXT: ret <2 x i32> [[COND]]
50 %sub = sub <2 x i32> zeroinitializer, %a
51 %and = and <2 x i32> %sub, %a
52 %lz = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %and, i1 true)
53 %tobool = icmp eq <2 x i32> %a, zeroinitializer
54 %sub1 = xor <2 x i32> %lz, <i32 31, i32 31>
55 %cond = select <2 x i1> %tobool, <2 x i32> %lz, <2 x i32> %sub1
59 define i32 @select_clz_to_ctz_extra_use(i32 %a) {
60 ; CHECK-LABEL: @select_clz_to_ctz_extra_use(
61 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]]
62 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[A]]
63 ; CHECK-NEXT: [[LZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[AND]], i1 true), !range !0
64 ; CHECK-NEXT: [[SUB1:%.*]] = xor i32 [[LZ]], 31
65 ; CHECK-NEXT: call void @use(i32 [[SUB1]])
66 ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.cttz.i32(i32 [[A]], i1 true), !range !0
67 ; CHECK-NEXT: ret i32 [[COND]]
70 %and = and i32 %sub, %a
71 %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true)
72 %tobool = icmp eq i32 %a, 0
73 %sub1 = xor i32 %lz, 31
74 call void @use(i32 %sub1)
75 %cond = select i1 %tobool, i32 %lz, i32 %sub1
79 define i32 @select_clz_to_ctz_and_commuted(i32 %a) {
80 ; CHECK-LABEL: @select_clz_to_ctz_and_commuted(
81 ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.cttz.i32(i32 [[A:%.*]], i1 true), !range !0
82 ; CHECK-NEXT: ret i32 [[COND]]
85 %and = and i32 %a, %sub
86 %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true)
87 %tobool = icmp eq i32 %a, 0
88 %sub1 = xor i32 %lz, 31
89 %cond = select i1 %tobool, i32 %lz, i32 %sub1
93 define i32 @select_clz_to_ctz_icmp_ne(i32 %a) {
94 ; CHECK-LABEL: @select_clz_to_ctz_icmp_ne(
95 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[A:%.*]], 0
96 ; CHECK-NEXT: call void @use2(i1 [[TOBOOL]])
97 ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.cttz.i32(i32 [[A]], i1 true), !range !0
98 ; CHECK-NEXT: ret i32 [[COND]]
101 %and = and i32 %sub, %a
102 %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true)
103 %tobool = icmp ne i32 %a, 0
104 call void @use2(i1 %tobool)
105 %sub1 = xor i32 %lz, 31
106 %cond = select i1 %tobool, i32 %sub1, i32 %lz
110 define i64 @select_clz_to_ctz_i64(i64 %a) {
111 ; CHECK-LABEL: @select_clz_to_ctz_i64(
112 ; CHECK-NEXT: [[COND:%.*]] = call i64 @llvm.cttz.i64(i64 [[A:%.*]], i1 true), !range !1
113 ; CHECK-NEXT: ret i64 [[COND]]
116 %and = and i64 %sub, %a
117 %lz = tail call i64 @llvm.ctlz.i64(i64 %and, i1 true)
118 %tobool = icmp eq i64 %a, 0
119 %sub1 = xor i64 %lz, 63
120 %cond = select i1 %tobool, i64 %lz, i64 %sub1
126 define i32 @select_clz_to_ctz_wrong_sub(i32 %a) {
127 ; CHECK-LABEL: @select_clz_to_ctz_wrong_sub(
128 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 1, [[A:%.*]]
129 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[A]]
130 ; CHECK-NEXT: [[LZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[AND]], i1 true), !range !0
131 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A]], 0
132 ; CHECK-NEXT: [[SUB1:%.*]] = xor i32 [[LZ]], 31
133 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[LZ]], i32 [[SUB1]]
134 ; CHECK-NEXT: ret i32 [[COND]]
137 %and = and i32 %sub, %a
138 %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true)
139 %tobool = icmp eq i32 %a, 0
140 %sub1 = xor i32 %lz, 31
141 %cond = select i1 %tobool, i32 %lz, i32 %sub1
145 define i64 @select_clz_to_ctz_i64_wrong_xor(i64 %a) {
146 ; CHECK-LABEL: @select_clz_to_ctz_i64_wrong_xor(
147 ; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[A:%.*]]
148 ; CHECK-NEXT: [[AND:%.*]] = and i64 [[SUB]], [[A]]
149 ; CHECK-NEXT: [[LZ:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[AND]], i1 true), !range !1
150 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A]], 0
151 ; CHECK-NEXT: [[SUB11:%.*]] = or i64 [[LZ]], 64
152 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[LZ]], i64 [[SUB11]]
153 ; CHECK-NEXT: ret i64 [[COND]]
156 %and = and i64 %sub, %a
157 %lz = tail call i64 @llvm.ctlz.i64(i64 %and, i1 true)
158 %tobool = icmp eq i64 %a, 0
159 %sub1 = xor i64 %lz, 64
160 %cond = select i1 %tobool, i64 %lz, i64 %sub1
164 define i64 @select_clz_to_ctz_i64_wrong_icmp_cst(i64 %a) {
165 ; CHECK-LABEL: @select_clz_to_ctz_i64_wrong_icmp_cst(
166 ; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[A:%.*]]
167 ; CHECK-NEXT: [[AND:%.*]] = and i64 [[SUB]], [[A]]
168 ; CHECK-NEXT: [[LZ:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[AND]], i1 true), !range !1
169 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A]], 1
170 ; CHECK-NEXT: [[SUB1:%.*]] = xor i64 [[LZ]], 63
171 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[LZ]], i64 [[SUB1]]
172 ; CHECK-NEXT: ret i64 [[COND]]
175 %and = and i64 %sub, %a
176 %lz = tail call i64 @llvm.ctlz.i64(i64 %and, i1 true)
177 %tobool = icmp eq i64 %a, 1
178 %sub1 = xor i64 %lz, 63
179 %cond = select i1 %tobool, i64 %lz, i64 %sub1
183 define i64 @select_clz_to_ctz_i64_wrong_icmp_pred(i64 %a) {
184 ; CHECK-LABEL: @select_clz_to_ctz_i64_wrong_icmp_pred(
185 ; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[A:%.*]]
186 ; CHECK-NEXT: [[AND:%.*]] = and i64 [[SUB]], [[A]]
187 ; CHECK-NEXT: [[LZ:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[AND]], i1 true), !range !1
188 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp slt i64 [[A]], 0
189 ; CHECK-NEXT: [[SUB1:%.*]] = xor i64 [[LZ]], 63
190 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[LZ]], i64 [[SUB1]]
191 ; CHECK-NEXT: ret i64 [[COND]]
194 %and = and i64 %sub, %a
195 %lz = tail call i64 @llvm.ctlz.i64(i64 %and, i1 true)
196 %tobool = icmp slt i64 %a, 0
197 %sub1 = xor i64 %lz, 63
198 %cond = select i1 %tobool, i64 %lz, i64 %sub1
202 define <2 x i32> @select_clz_to_ctz_vec_with_undef(<2 x i32> %a) {
203 ; CHECK-LABEL: @select_clz_to_ctz_vec_with_undef(
204 ; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> zeroinitializer, [[A:%.*]]
205 ; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[SUB]], [[A]]
206 ; CHECK-NEXT: [[LZ:%.*]] = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[AND]], i1 true)
207 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq <2 x i32> [[A]], zeroinitializer
208 ; CHECK-NEXT: [[SUB1:%.*]] = xor <2 x i32> [[LZ]], <i32 31, i32 undef>
209 ; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[TOBOOL]], <2 x i32> [[LZ]], <2 x i32> [[SUB1]]
210 ; CHECK-NEXT: ret <2 x i32> [[COND]]
212 %sub = sub <2 x i32> zeroinitializer, %a
213 %and = and <2 x i32> %sub, %a
214 %lz = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %and, i1 true)
215 %tobool = icmp eq <2 x i32> %a, zeroinitializer
216 %sub1 = xor <2 x i32> %lz, <i32 31, i32 undef>
217 %cond = select <2 x i1> %tobool, <2 x i32> %lz, <2 x i32> %sub1