[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / Transforms / InstCombine / select-ctlz-to-cttz.ll
blob3e704aec015f5877440266b489f1855ba24ed60e
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -instcombine -S < %s | FileCheck %s
4 declare i3 @llvm.cttz.i3(i3, i1)
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 [[RNG0:![0-9]+]]
20 ; CHECK-NEXT:    ret i32 [[COND]]
22   %sub = sub i32 0, %a
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
28   ret i32 %cond
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 [[RNG0]]
34 ; CHECK-NEXT:    ret i32 [[COND]]
36   %sub = sub i32 0, %a
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
42   ret i32 %cond
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
56   ret <2 x i32> %cond
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 [[RNG0]]
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 [[RNG0]]
67 ; CHECK-NEXT:    ret i32 [[COND]]
69   %sub = sub i32 0, %a
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
76   ret i32 %cond
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 [[RNG0]]
82 ; CHECK-NEXT:    ret i32 [[COND]]
84   %sub = sub i32 0, %a
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
90   ret i32 %cond
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 [[RNG0]]
98 ; CHECK-NEXT:    ret i32 [[COND]]
100   %sub = sub i32 0, %a
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
107   ret i32 %cond
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 [[RNG1:![0-9]+]]
113 ; CHECK-NEXT:    ret i64 [[COND]]
115   %sub = sub i64 0, %a
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
121   ret i64 %cond
124 ; Negative tests
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 [[RNG0]]
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]]
136   %sub = sub i32 1, %a
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
142   ret i32 %cond
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 [[RNG1]]
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]]
155   %sub = sub i64 0, %a
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
161   ret i64 %cond
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 [[RNG1]]
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]]
174   %sub = sub i64 0, %a
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
180   ret i64 %cond
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 [[RNG1]]
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]]
193   %sub = sub i64 0, %a
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
199   ret i64 %cond
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
218   ret <2 x i32> %cond
221 define i4 @PR45762(i3 %x4) {
222 ; CHECK-LABEL: @PR45762(
223 ; CHECK-NEXT:    [[T4:%.*]] = call i3 @llvm.cttz.i3(i3 [[X4:%.*]], i1 false), !range [[RNG2:![0-9]+]]
224 ; CHECK-NEXT:    [[T7:%.*]] = zext i3 [[T4]] to i4
225 ; CHECK-NEXT:    [[ONE_HOT_16:%.*]] = shl i4 1, [[T7]]
226 ; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq i3 [[X4]], 0
227 ; CHECK-NEXT:    [[UMUL_23:%.*]] = select i1 [[DOTNOT]], i4 0, i4 [[T7]]
228 ; CHECK-NEXT:    [[SEL_71:%.*]] = shl i4 [[ONE_HOT_16]], [[UMUL_23]]
229 ; CHECK-NEXT:    ret i4 [[SEL_71]]
231   %t4 = call i3 @llvm.cttz.i3(i3 %x4, i1 false)
232   %t5 = icmp eq i3 %x4, 0
233   %t6 = select i1 %t5, i3 3, i3 %t4
234   %t7 = zext i3 %t6 to i4
235   %one_hot_16 = shl i4 1, %t7
236   %t8 = lshr i4 %one_hot_16, 0
237   %bit_slice_61 = trunc i4 %t8 to i1
238   %t9 = lshr i4 %one_hot_16, 1
239   %bit_slice_62 = trunc i4 %t9 to i1
240   %t10 = lshr i4 %one_hot_16, 2
241   %bit_slice_64 = trunc i4 %t10 to i1
242   %t11 = or i1 %bit_slice_61, %bit_slice_62
243   %or_69 = or i1 %t11, %bit_slice_64
244   %umul_23 = mul i4 %one_hot_16, %one_hot_16
245   %t12 = icmp eq i1 %or_69, false
246   %sel_71 = select i1 %t12, i4 %one_hot_16, i4 %umul_23
247   ret i4 %sel_71
250 define i4 @PR45762_logical(i3 %x4) {
251 ; CHECK-LABEL: @PR45762_logical(
252 ; CHECK-NEXT:    [[T4:%.*]] = call i3 @llvm.cttz.i3(i3 [[X4:%.*]], i1 false), !range [[RNG2]]
253 ; CHECK-NEXT:    [[T7:%.*]] = zext i3 [[T4]] to i4
254 ; CHECK-NEXT:    [[ONE_HOT_16:%.*]] = shl i4 1, [[T7]]
255 ; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq i3 [[X4]], 0
256 ; CHECK-NEXT:    [[UMUL_23:%.*]] = select i1 [[DOTNOT]], i4 0, i4 [[T7]]
257 ; CHECK-NEXT:    [[SEL_71:%.*]] = shl i4 [[ONE_HOT_16]], [[UMUL_23]]
258 ; CHECK-NEXT:    ret i4 [[SEL_71]]
260   %t4 = call i3 @llvm.cttz.i3(i3 %x4, i1 false)
261   %t5 = icmp eq i3 %x4, 0
262   %t6 = select i1 %t5, i3 3, i3 %t4
263   %t7 = zext i3 %t6 to i4
264   %one_hot_16 = shl i4 1, %t7
265   %t8 = lshr i4 %one_hot_16, 0
266   %bit_slice_61 = trunc i4 %t8 to i1
267   %t9 = lshr i4 %one_hot_16, 1
268   %bit_slice_62 = trunc i4 %t9 to i1
269   %t10 = lshr i4 %one_hot_16, 2
270   %bit_slice_64 = trunc i4 %t10 to i1
271   %t11 = select i1 %bit_slice_61, i1 true, i1 %bit_slice_62
272   %or_69 = select i1 %t11, i1 true, i1 %bit_slice_64
273   %umul_23 = mul i4 %one_hot_16, %one_hot_16
274   %t12 = icmp eq i1 %or_69, false
275   %sel_71 = select i1 %t12, i4 %one_hot_16, i4 %umul_23
276   ret i4 %sel_71