Revert "[InstCombine] Support gep nuw in icmp folds" (#118698)
[llvm-project.git] / llvm / test / Transforms / InstCombine / binop-cast.ll
blob7330d4409829950a73b041233aa2bf2d84e14fd7
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 declare void @use(i32)
5 declare void @use_vec(<2 x i32>)
7 define i32 @testAdd(i32 %X, i32 %Y) {
8 ; CHECK-LABEL: @testAdd(
9 ; CHECK-NEXT:    [[T:%.*]] = add i32 [[X:%.*]], [[Y:%.*]]
10 ; CHECK-NEXT:    ret i32 [[T]]
12   %t = add i32 %X, %Y
13   %tl = bitcast i32 %t to i32
14   ret i32 %tl
17 define i32 @and_sext_to_sel(i32 %x, i1 %y) {
18 ; CHECK-LABEL: @and_sext_to_sel(
19 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y:%.*]], i32 [[X:%.*]], i32 0
20 ; CHECK-NEXT:    ret i32 [[R]]
22   %sext = sext i1 %y to i32
23   %r = and i32 %sext, %x
24   ret i32 %r
27 define <2 x i32> @and_sext_to_sel_constant_vec(<2 x i1> %y) {
28 ; CHECK-LABEL: @and_sext_to_sel_constant_vec(
29 ; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> <i32 42, i32 -7>, <2 x i32> zeroinitializer
30 ; CHECK-NEXT:    ret <2 x i32> [[R]]
32   %sext = sext <2 x i1> %y to <2 x i32>
33   %r = and <2 x i32> <i32 42, i32 -7>, %sext
34   ret <2 x i32> %r
37 define <2 x i32> @and_sext_to_sel_swap(<2 x i32> %px, <2 x i1> %y) {
38 ; CHECK-LABEL: @and_sext_to_sel_swap(
39 ; CHECK-NEXT:    [[X:%.*]] = mul <2 x i32> [[PX:%.*]], [[PX]]
40 ; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> [[X]], <2 x i32> zeroinitializer
41 ; CHECK-NEXT:    ret <2 x i32> [[R]]
43   %x = mul <2 x i32> %px, %px ; thwart complexity-based canonicalization
44   %sext = sext <2 x i1> %y to <2 x i32>
45   %r = and <2 x i32> %x, %sext
46   ret <2 x i32> %r
49 define i32 @and_sext_to_sel_multi_use(i32 %x, i1 %y) {
50 ; CHECK-LABEL: @and_sext_to_sel_multi_use(
51 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
52 ; CHECK-NEXT:    call void @use(i32 [[SEXT]])
53 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y]], i32 [[X:%.*]], i32 0
54 ; CHECK-NEXT:    ret i32 [[R]]
56   %sext = sext i1 %y to i32
57   call void @use(i32 %sext)
58   %r = and i32 %sext, %x
59   ret i32 %r
62 define i32 @and_sext_to_sel_multi_use_constant_mask(i1 %y) {
63 ; CHECK-LABEL: @and_sext_to_sel_multi_use_constant_mask(
64 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
65 ; CHECK-NEXT:    call void @use(i32 [[SEXT]])
66 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y]], i32 42, i32 0
67 ; CHECK-NEXT:    ret i32 [[R]]
69   %sext = sext i1 %y to i32
70   call void @use(i32 %sext)
71   %r = and i32 %sext, 42
72   ret i32 %r
75 define <2 x i32> @and_not_sext_to_sel(<2 x i32> %x, <2 x i1> %y) {
76 ; CHECK-LABEL: @and_not_sext_to_sel(
77 ; CHECK-NEXT:    [[SEXT:%.*]] = sext <2 x i1> [[Y:%.*]] to <2 x i32>
78 ; CHECK-NEXT:    call void @use_vec(<2 x i32> [[SEXT]])
79 ; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[Y]], <2 x i32> zeroinitializer, <2 x i32> [[X:%.*]]
80 ; CHECK-NEXT:    ret <2 x i32> [[R]]
82   %sext = sext <2 x i1> %y to <2 x i32>
83   call void @use_vec(<2 x i32> %sext)
84   %not = xor <2 x i32> %sext, <i32 -1, i32 -1>
85   %r = and <2 x i32> %not, %x
86   ret <2 x i32> %r
89 define i32 @and_not_sext_to_sel_commute(i32 %px, i1 %y) {
90 ; CHECK-LABEL: @and_not_sext_to_sel_commute(
91 ; CHECK-NEXT:    [[X:%.*]] = mul i32 [[PX:%.*]], [[PX]]
92 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
93 ; CHECK-NEXT:    call void @use(i32 [[SEXT]])
94 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[SEXT]], -1
95 ; CHECK-NEXT:    call void @use(i32 [[NOT]])
96 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y]], i32 0, i32 [[X]]
97 ; CHECK-NEXT:    ret i32 [[R]]
99   %x = mul i32 %px, %px ; thwart complexity-based canonicalization
100   %sext = sext i1 %y to i32
101   call void @use(i32 %sext)
102   %not = xor i32 %sext, -1
103   call void @use(i32 %not)
104   %r = and i32 %x, %not
105   ret i32 %r
108 ; negative test - must be 'not'
110 define i32 @and_xor_sext_to_sel(i32 %x, i1 %y) {
111 ; CHECK-LABEL: @and_xor_sext_to_sel(
112 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
113 ; CHECK-NEXT:    call void @use(i32 [[SEXT]])
114 ; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[SEXT]], -2
115 ; CHECK-NEXT:    [[R:%.*]] = and i32 [[XOR]], [[X:%.*]]
116 ; CHECK-NEXT:    ret i32 [[R]]
118   %sext = sext i1 %y to i32
119   call void @use(i32 %sext)
120   %xor = xor i32 %sext, -2
121   %r = and i32 %xor, %x
122   ret i32 %r
125 ; negative test - must be 'sext'
127 define i32 @and_not_zext_to_sel(i32 %x, i1 %y) {
128 ; CHECK-LABEL: @and_not_zext_to_sel(
129 ; CHECK-NEXT:    [[ZEXT:%.*]] = zext i1 [[Y:%.*]] to i32
130 ; CHECK-NEXT:    call void @use(i32 [[ZEXT]])
131 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[ZEXT]], -1
132 ; CHECK-NEXT:    [[R:%.*]] = and i32 [[X:%.*]], [[NOT]]
133 ; CHECK-NEXT:    ret i32 [[R]]
135   %zext = zext i1 %y to i32
136   call void @use(i32 %zext)
137   %not = xor i32 %zext, -1
138   %r = and i32 %not, %x
139   ret i32 %r
142 define i32 @or_sext_to_sel(i32 %x, i1 %y) {
143 ; CHECK-LABEL: @or_sext_to_sel(
144 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y:%.*]], i32 -1, i32 [[X:%.*]]
145 ; CHECK-NEXT:    ret i32 [[R]]
147   %sext = sext i1 %y to i32
148   %r = or i32 %sext, %x
149   ret i32 %r
152 define <2 x i32> @or_sext_to_sel_constant_vec(<2 x i1> %y) {
153 ; CHECK-LABEL: @or_sext_to_sel_constant_vec(
154 ; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> splat (i32 -1), <2 x i32> <i32 42, i32 -7>
155 ; CHECK-NEXT:    ret <2 x i32> [[R]]
157   %sext = sext <2 x i1> %y to <2 x i32>
158   %r = or <2 x i32> <i32 42, i32 -7>, %sext
159   ret <2 x i32> %r
162 define <2 x i32> @or_sext_to_sel_swap(<2 x i32> %px, <2 x i1> %y) {
163 ; CHECK-LABEL: @or_sext_to_sel_swap(
164 ; CHECK-NEXT:    [[X:%.*]] = mul <2 x i32> [[PX:%.*]], [[PX]]
165 ; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> splat (i32 -1), <2 x i32> [[X]]
166 ; CHECK-NEXT:    ret <2 x i32> [[R]]
168   %x = mul <2 x i32> %px, %px ; thwart complexity-based canonicalization
169   %sext = sext <2 x i1> %y to <2 x i32>
170   %r = or <2 x i32> %x, %sext
171   ret <2 x i32> %r
174 define i32 @or_sext_to_sel_multi_use(i32 %x, i1 %y) {
175 ; CHECK-LABEL: @or_sext_to_sel_multi_use(
176 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
177 ; CHECK-NEXT:    call void @use(i32 [[SEXT]])
178 ; CHECK-NEXT:    [[R:%.*]] = or i32 [[X:%.*]], [[SEXT]]
179 ; CHECK-NEXT:    ret i32 [[R]]
181   %sext = sext i1 %y to i32
182   call void @use(i32 %sext)
183   %r = or i32 %sext, %x
184   ret i32 %r
187 define i32 @or_sext_to_sel_multi_use_constant_mask(i1 %y) {
188 ; CHECK-LABEL: @or_sext_to_sel_multi_use_constant_mask(
189 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
190 ; CHECK-NEXT:    call void @use(i32 [[SEXT]])
191 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y]], i32 -1, i32 42
192 ; CHECK-NEXT:    ret i32 [[R]]
194   %sext = sext i1 %y to i32
195   call void @use(i32 %sext)
196   %r = or i32 %sext, 42
197   ret i32 %r
200 define i32 @xor_sext_to_sel(i32 %x, i1 %y) {
201 ; CHECK-LABEL: @xor_sext_to_sel(
202 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
203 ; CHECK-NEXT:    [[R:%.*]] = xor i32 [[X:%.*]], [[SEXT]]
204 ; CHECK-NEXT:    ret i32 [[R]]
206   %sext = sext i1 %y to i32
207   %r = xor i32 %sext, %x
208   ret i32 %r
211 define <2 x i32> @xor_sext_to_sel_constant_vec(<2 x i1> %y) {
212 ; CHECK-LABEL: @xor_sext_to_sel_constant_vec(
213 ; CHECK-NEXT:    [[SEXT:%.*]] = sext <2 x i1> [[Y:%.*]] to <2 x i32>
214 ; CHECK-NEXT:    [[R:%.*]] = xor <2 x i32> [[SEXT]], <i32 42, i32 -7>
215 ; CHECK-NEXT:    ret <2 x i32> [[R]]
217   %sext = sext <2 x i1> %y to <2 x i32>
218   %r = xor <2 x i32> <i32 42, i32 -7>, %sext
219   ret <2 x i32> %r
222 define <2 x i32> @xor_sext_to_sel_swap(<2 x i32> %px, <2 x i1> %y) {
223 ; CHECK-LABEL: @xor_sext_to_sel_swap(
224 ; CHECK-NEXT:    [[X:%.*]] = mul <2 x i32> [[PX:%.*]], [[PX]]
225 ; CHECK-NEXT:    [[SEXT:%.*]] = sext <2 x i1> [[Y:%.*]] to <2 x i32>
226 ; CHECK-NEXT:    [[R:%.*]] = xor <2 x i32> [[X]], [[SEXT]]
227 ; CHECK-NEXT:    ret <2 x i32> [[R]]
229   %x = mul <2 x i32> %px, %px ; thwart complexity-based canonicalization
230   %sext = sext <2 x i1> %y to <2 x i32>
231   %r = xor <2 x i32> %x, %sext
232   ret <2 x i32> %r
235 define i32 @xor_sext_to_sel_multi_use(i32 %x, i1 %y) {
236 ; CHECK-LABEL: @xor_sext_to_sel_multi_use(
237 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
238 ; CHECK-NEXT:    call void @use(i32 [[SEXT]])
239 ; CHECK-NEXT:    [[R:%.*]] = xor i32 [[X:%.*]], [[SEXT]]
240 ; CHECK-NEXT:    ret i32 [[R]]
242   %sext = sext i1 %y to i32
243   call void @use(i32 %sext)
244   %r = xor i32 %sext, %x
245   ret i32 %r
248 define i32 @xor_sext_to_sel_multi_use_constant_mask(i1 %y) {
249 ; CHECK-LABEL: @xor_sext_to_sel_multi_use_constant_mask(
250 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
251 ; CHECK-NEXT:    call void @use(i32 [[SEXT]])
252 ; CHECK-NEXT:    [[R:%.*]] = xor i32 [[SEXT]], 42
253 ; CHECK-NEXT:    ret i32 [[R]]
255   %sext = sext i1 %y to i32
256   call void @use(i32 %sext)
257   %r = xor i32 %sext, 42
258   ret i32 %r
261 define i64 @PR63321(ptr %ptr, i64 %c) {
262 ; CHECK-LABEL: @PR63321(
263 ; CHECK-NEXT:    [[VAL:%.*]] = load i8, ptr [[PTR:%.*]], align 1, !range [[RNG0:![0-9]+]]
264 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[VAL]], 0
265 ; CHECK-NEXT:    [[RES:%.*]] = select i1 [[TMP1]], i64 [[C:%.*]], i64 0
266 ; CHECK-NEXT:    ret i64 [[RES]]
268   %val = load i8, ptr %ptr, align 1, !range !{i8 0, i8 2}
269   %rhs = zext i8 %val to i64
270   %mask = add i64 -1, %rhs
271   %res = and i64 %mask, %c
272   ret i64 %res
275 ; Negative test of PR63321
276 define i64 @and_add_non_bool(ptr %ptr, i64 %c) {
277 ; CHECK-LABEL: @and_add_non_bool(
278 ; CHECK-NEXT:    [[VAL:%.*]] = load i8, ptr [[PTR:%.*]], align 1, !range [[RNG1:![0-9]+]]
279 ; CHECK-NEXT:    [[RHS:%.*]] = zext nneg i8 [[VAL]] to i64
280 ; CHECK-NEXT:    [[MASK:%.*]] = add nsw i64 [[RHS]], -1
281 ; CHECK-NEXT:    [[RES:%.*]] = and i64 [[MASK]], [[C:%.*]]
282 ; CHECK-NEXT:    ret i64 [[RES]]
284   %val = load i8, ptr %ptr, align 1, !range !{i8 0, i8 3}
285   %rhs = zext i8 %val to i64
286   %mask = add i64 -1, %rhs
287   %res = and i64 %mask, %c
288   ret i64 %res
291 define i32 @and_add_bool_to_select(i1 %x, i32 %y) {
292 ; CHECK-LABEL: @and_add_bool_to_select(
293 ; CHECK-NEXT:    [[RES:%.*]] = select i1 [[X:%.*]], i32 0, i32 [[Y:%.*]]
294 ; CHECK-NEXT:    ret i32 [[RES]]
296   %val = zext i1 %x to i32
297   %mask = add i32 -1, %val
298   %res = and i32 %mask, %y
299   ret i32 %res
302 define i32 @and_add_bool_no_fold(i32 %y) {
303 ; CHECK-LABEL: @and_add_bool_no_fold(
304 ; CHECK-NEXT:    [[X:%.*]] = and i32 [[Y:%.*]], 1
305 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[X]], 0
306 ; CHECK-NEXT:    [[RES:%.*]] = select i1 [[TMP1]], i32 [[Y]], i32 0
307 ; CHECK-NEXT:    ret i32 [[RES]]
309   %x = and i32 %y, 1
310   %mask = add i32 -1, %x
311   %res = and i32 %mask, %y
312   ret i32 %res
315 define <2 x i32> @and_add_bool_vec_to_select(<2 x i1> %x, <2 x i32> %y) {
316 ; CHECK-LABEL: @and_add_bool_vec_to_select(
317 ; CHECK-NEXT:    [[RES:%.*]] = select <2 x i1> [[X:%.*]], <2 x i32> zeroinitializer, <2 x i32> [[Y:%.*]]
318 ; CHECK-NEXT:    ret <2 x i32> [[RES]]
320   %val = zext <2 x i1> %x to <2 x i32>
321   %mask = add <2 x i32> <i32 -1, i32 -1>, %val
322   %res = and <2 x i32> %mask, %y
323   ret <2 x i32> %res
326 ; Negative test of and_add_bool_to_select
327 define i32 @and_add_bool_to_select_multi_use(i1 %x, i32 %y) {
328 ; CHECK-LABEL: @and_add_bool_to_select_multi_use(
329 ; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[Y:%.*]], -1
330 ; CHECK-NEXT:    [[RET:%.*]] = select i1 [[X:%.*]], i32 0, i32 [[TMP1]]
331 ; CHECK-NEXT:    ret i32 [[RET]]
333   %val = zext i1 %x to i32
334   %mask = add i32 -1, %val
335   %res = and i32 %mask, %y
336   %ret = add i32 %res, %mask
337   ret i32 %ret