1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3 ; RUN: opt < %s -passes=instcombine -use-constant-int-for-fixed-length-splat -S | FileCheck %s
5 declare i32 @llvm.abs.i32(i32, i1)
7 define i32 @pow2_multiplier(i32 %A) {
8 ; CHECK-LABEL: @pow2_multiplier(
9 ; CHECK-NEXT: [[B:%.*]] = shl i32 [[A:%.*]], 1
10 ; CHECK-NEXT: ret i32 [[B]]
16 define <2 x i32> @pow2_multiplier_vec(<2 x i32> %A) {
17 ; CHECK-LABEL: @pow2_multiplier_vec(
18 ; CHECK-NEXT: [[B:%.*]] = shl <2 x i32> [[A:%.*]], splat (i32 3)
19 ; CHECK-NEXT: ret <2 x i32> [[B]]
21 %B = mul <2 x i32> %A, <i32 8, i32 8>
25 define i8 @combine_shl(i8 %A) {
26 ; CHECK-LABEL: @combine_shl(
27 ; CHECK-NEXT: [[C:%.*]] = shl i8 [[A:%.*]], 6
28 ; CHECK-NEXT: ret i8 [[C]]
35 define i32 @neg(i32 %i) {
37 ; CHECK-NEXT: [[T:%.*]] = sub i32 0, [[I:%.*]]
38 ; CHECK-NEXT: ret i32 [[T]]
44 ; Use the sign-bit as a mask:
45 ; (zext (A < 0)) * B --> (A >> 31) & B
47 define i32 @test10(i32 %a, i32 %b) {
48 ; CHECK-LABEL: @test10(
49 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A:%.*]], 0
50 ; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 0
51 ; CHECK-NEXT: ret i32 [[E]]
53 %c = icmp slt i32 %a, 0
54 %d = zext i1 %c to i32
59 define i32 @test11(i32 %a, i32 %b) {
60 ; CHECK-LABEL: @test11(
61 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A:%.*]], 0
62 ; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 0
63 ; CHECK-NEXT: ret i32 [[E]]
65 %c = icmp sle i32 %a, -1
66 %d = zext i1 %c to i32
71 declare void @use32(i32)
73 define i32 @test12(i32 %a, i32 %b) {
74 ; CHECK-LABEL: @test12(
75 ; CHECK-NEXT: [[A_LOBIT:%.*]] = lshr i32 [[A:%.*]], 31
76 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A]], 0
77 ; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 0
78 ; CHECK-NEXT: call void @use32(i32 [[A_LOBIT]])
79 ; CHECK-NEXT: ret i32 [[E]]
81 %c = icmp ugt i32 %a, 2147483647
82 %d = zext i1 %c to i32
84 call void @use32(i32 %d)
89 define i32 @shl1(i32 %a, i32 %b) {
91 ; CHECK-NEXT: [[M1:%.*]] = shl i32 [[A:%.*]], [[B:%.*]]
92 ; CHECK-NEXT: ret i32 [[M1]]
99 define i32 @shl1_nsw_nsw(i32 %A, i32 %B) {
100 ; CHECK-LABEL: @shl1_nsw_nsw(
101 ; CHECK-NEXT: [[D1:%.*]] = shl nsw i32 [[A:%.*]], [[B:%.*]]
102 ; CHECK-NEXT: ret i32 [[D1]]
104 %shl = shl nsw i32 1, %B
105 %D = mul nsw i32 %A, %shl
109 define <2 x i32> @shl1_nsw_nsw_commute(<2 x i32> %A, <2 x i32> %B) {
110 ; CHECK-LABEL: @shl1_nsw_nsw_commute(
111 ; CHECK-NEXT: [[D1:%.*]] = shl nsw <2 x i32> [[A:%.*]], [[B:%.*]]
112 ; CHECK-NEXT: ret <2 x i32> [[D1]]
114 %shl = shl nsw <2 x i32> <i32 1, i32 poison>, %B
115 %D = mul nsw <2 x i32> %shl, %A
119 define i32 @shl1_nuw(i32 %A, i32 %B) {
120 ; CHECK-LABEL: @shl1_nuw(
121 ; CHECK-NEXT: [[D1:%.*]] = shl nuw i32 [[A:%.*]], [[B:%.*]]
122 ; CHECK-NEXT: ret i32 [[D1]]
125 %D = mul nuw i32 %A, %shl
129 define i32 @shl1_nuw_commute(i32 %A, i32 %B) {
130 ; CHECK-LABEL: @shl1_nuw_commute(
131 ; CHECK-NEXT: [[D1:%.*]] = shl i32 [[A:%.*]], [[B:%.*]]
132 ; CHECK-NEXT: ret i32 [[D1]]
134 %shl = shl nuw i32 1, %B
135 %D = mul i32 %shl, %A
139 define i32 @shl1_nsw(i32 %A) {
140 ; CHECK-LABEL: @shl1_nsw(
141 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, [[A:%.*]]
142 ; CHECK-NEXT: [[C1:%.*]] = shl i32 [[SHL]], [[A]]
143 ; CHECK-NEXT: ret i32 [[C1]]
146 %C = mul nsw i32 %shl, %shl
150 define i5 @shl1_increment(i5 %x, i5 %y) {
151 ; CHECK-LABEL: @shl1_increment(
152 ; CHECK-NEXT: [[Y_FR:%.*]] = freeze i5 [[Y:%.*]]
153 ; CHECK-NEXT: [[MULSHL:%.*]] = shl i5 [[Y_FR]], [[X:%.*]]
154 ; CHECK-NEXT: [[M1:%.*]] = add i5 [[MULSHL]], [[Y_FR]]
155 ; CHECK-NEXT: ret i5 [[M1]]
157 %pow2x = shl i5 1, %x
158 %x1 = add i5 %pow2x, 1
163 define <3 x i5> @shl1_nuw_increment_commute(<3 x i5> %x, <3 x i5> noundef %p) {
164 ; CHECK-LABEL: @shl1_nuw_increment_commute(
165 ; CHECK-NEXT: [[Y:%.*]] = ashr <3 x i5> [[P:%.*]], splat (i5 1)
166 ; CHECK-NEXT: [[MULSHL:%.*]] = shl nuw <3 x i5> [[Y]], [[X:%.*]]
167 ; CHECK-NEXT: [[M1:%.*]] = add nuw <3 x i5> [[MULSHL]], [[Y]]
168 ; CHECK-NEXT: ret <3 x i5> [[M1]]
170 %y = ashr <3 x i5> %p, <i5 1, i5 1, i5 1> ; thwart complexity-based canonicalization
171 %pow2x = shl <3 x i5> <i5 1, i5 poison, i5 1>, %x
172 %x1 = add <3 x i5> %pow2x, <i5 1, i5 poison, i5 1>
173 %m = mul nuw <3 x i5> %y, %x1
177 define i5 @shl1_nsw_increment(i5 %x, i5 %y) {
178 ; CHECK-LABEL: @shl1_nsw_increment(
179 ; CHECK-NEXT: [[Y_FR:%.*]] = freeze i5 [[Y:%.*]]
180 ; CHECK-NEXT: [[MULSHL:%.*]] = shl i5 [[Y_FR]], [[X:%.*]]
181 ; CHECK-NEXT: [[M1:%.*]] = add i5 [[MULSHL]], [[Y_FR]]
182 ; CHECK-NEXT: ret i5 [[M1]]
184 %pow2x = shl i5 1, %x
185 %x1 = add i5 %pow2x, 1
186 %m = mul nsw i5 %x1, %y
190 define i5 @shl1_nsw_nsw_increment(i5 %x, i5 %y) {
191 ; CHECK-LABEL: @shl1_nsw_nsw_increment(
192 ; CHECK-NEXT: [[Y_FR:%.*]] = freeze i5 [[Y:%.*]]
193 ; CHECK-NEXT: [[MULSHL:%.*]] = shl nsw i5 [[Y_FR]], [[X:%.*]]
194 ; CHECK-NEXT: [[M1:%.*]] = add nsw i5 [[MULSHL]], [[Y_FR]]
195 ; CHECK-NEXT: ret i5 [[M1]]
197 %pow2x = shl nsw i5 1, %x
198 %x1 = add i5 %pow2x, 1
199 %m = mul nsw i5 %y, %x1
203 define i5 @shl1_nsw_nsw_increment_commute(i5 %x, i5 %y) {
204 ; CHECK-LABEL: @shl1_nsw_nsw_increment_commute(
205 ; CHECK-NEXT: [[Y_FR:%.*]] = freeze i5 [[Y:%.*]]
206 ; CHECK-NEXT: [[MULSHL:%.*]] = shl i5 [[Y_FR]], [[X:%.*]]
207 ; CHECK-NEXT: [[M1:%.*]] = add i5 [[MULSHL]], [[Y_FR]]
208 ; CHECK-NEXT: ret i5 [[M1]]
210 %pow2x = shl nsw i5 1, %x
211 %x1 = add nsw i5 %pow2x, 1
216 define i32 @shl1_increment_use(i32 %x, i32 %y) {
217 ; CHECK-LABEL: @shl1_increment_use(
218 ; CHECK-NEXT: [[POW2X:%.*]] = shl nuw i32 1, [[X:%.*]]
219 ; CHECK-NEXT: call void @use32(i32 [[POW2X]])
220 ; CHECK-NEXT: [[X1:%.*]] = add nuw i32 [[POW2X]], 1
221 ; CHECK-NEXT: [[M:%.*]] = mul i32 [[X1]], [[Y:%.*]]
222 ; CHECK-NEXT: ret i32 [[M]]
224 %pow2x = shl i32 1, %x
225 call void @use32(i32 %pow2x)
226 %x1 = add i32 %pow2x, 1
231 ; ((-1 << x) ^ -1) * y --> (y << x) - y
233 define i8 @shl1_decrement(i8 %x, i8 %y) {
234 ; CHECK-LABEL: @shl1_decrement(
235 ; CHECK-NEXT: [[Y_FR:%.*]] = freeze i8 [[Y:%.*]]
236 ; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y_FR]], [[X:%.*]]
237 ; CHECK-NEXT: [[M1:%.*]] = sub i8 [[MULSHL]], [[Y_FR]]
238 ; CHECK-NEXT: ret i8 [[M1]]
240 %pow2x = shl i8 -1, %x
241 %x1 = xor i8 %pow2x, -1
246 define i8 @shl1_decrement_commute(i8 %x, i8 noundef %p) {
247 ; CHECK-LABEL: @shl1_decrement_commute(
248 ; CHECK-NEXT: [[Y:%.*]] = ashr i8 [[P:%.*]], 1
249 ; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y]], [[X:%.*]]
250 ; CHECK-NEXT: [[M1:%.*]] = sub i8 [[MULSHL]], [[Y]]
251 ; CHECK-NEXT: ret i8 [[M1]]
253 %y = ashr i8 %p, 1 ; thwart complexity-based canonicalization
254 %pow2x = shl i8 1, %x
255 %x1 = add i8 %pow2x, -1
260 define i8 @shl1_nuw_decrement(i8 %x, i8 %y) {
261 ; CHECK-LABEL: @shl1_nuw_decrement(
262 ; CHECK-NEXT: [[Y_FR:%.*]] = freeze i8 [[Y:%.*]]
263 ; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y_FR]], [[X:%.*]]
264 ; CHECK-NEXT: [[M1:%.*]] = sub i8 [[MULSHL]], [[Y_FR]]
265 ; CHECK-NEXT: ret i8 [[M1]]
267 %pow2x = shl i8 -1, %x
268 %x1 = xor i8 %pow2x, -1
269 %m = mul nuw i8 %x1, %y
273 define i8 @shl1_nsw_decrement(i8 %x, i8 %y) {
274 ; CHECK-LABEL: @shl1_nsw_decrement(
275 ; CHECK-NEXT: [[Y_FR:%.*]] = freeze i8 [[Y:%.*]]
276 ; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y_FR]], [[X:%.*]]
277 ; CHECK-NEXT: [[M1:%.*]] = sub i8 [[MULSHL]], [[Y_FR]]
278 ; CHECK-NEXT: ret i8 [[M1]]
280 %pow2x = shl nsw i8 -1, %x
281 %x1 = xor i8 %pow2x, -1
282 %m = mul nsw i8 %x1, %y
286 ; negative test - extra use would require more instructions
288 define i32 @shl1_decrement_use(i32 %x, i32 %y) {
289 ; CHECK-LABEL: @shl1_decrement_use(
290 ; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i32 -1, [[X:%.*]]
291 ; CHECK-NEXT: [[X1:%.*]] = xor i32 [[NOTMASK]], -1
292 ; CHECK-NEXT: call void @use32(i32 [[X1]])
293 ; CHECK-NEXT: [[M:%.*]] = mul i32 [[Y:%.*]], [[X1]]
294 ; CHECK-NEXT: ret i32 [[M]]
296 %pow2x = shl i32 1, %x
297 %x1 = add i32 %pow2x, -1
298 call void @use32(i32 %x1)
303 ; the fold works for vectors too and if 'y' is a constant, sub becomes add
305 define <2 x i8> @shl1_decrement_vec(<2 x i8> %x) {
306 ; CHECK-LABEL: @shl1_decrement_vec(
307 ; CHECK-NEXT: [[MULSHL:%.*]] = shl <2 x i8> <i8 42, i8 -3>, [[X:%.*]]
308 ; CHECK-NEXT: [[M1:%.*]] = add <2 x i8> [[MULSHL]], <i8 -42, i8 3>
309 ; CHECK-NEXT: ret <2 x i8> [[M1]]
311 %pow2x = shl <2 x i8> <i8 -1, i8 -1>, %x
312 %x1 = xor <2 x i8> %pow2x, <i8 -1, i8 -1>
313 %m = mul <2 x i8> %x1, <i8 42, i8 -3>
317 ; X * Y (when Y is a boolean) --> Y ? X : 0
319 define i32 @mul_bool(i32 %x, i1 %y) {
320 ; CHECK-LABEL: @mul_bool(
321 ; CHECK-NEXT: [[M:%.*]] = select i1 [[Y:%.*]], i32 [[X:%.*]], i32 0
322 ; CHECK-NEXT: ret i32 [[M]]
324 %z = zext i1 %y to i32
329 define <2 x i32> @mul_bool_vec(<2 x i32> %x, <2 x i1> %y) {
330 ; CHECK-LABEL: @mul_bool_vec(
331 ; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> [[X:%.*]], <2 x i32> zeroinitializer
332 ; CHECK-NEXT: ret <2 x i32> [[M]]
334 %z = zext <2 x i1> %y to <2 x i32>
335 %m = mul <2 x i32> %z, %x
339 define <2 x i32> @mul_bool_vec_commute(<2 x i32> %px, <2 x i1> %y) {
340 ; CHECK-LABEL: @mul_bool_vec_commute(
341 ; CHECK-NEXT: [[X:%.*]] = mul <2 x i32> [[PX:%.*]], [[PX]]
342 ; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> [[X]], <2 x i32> zeroinitializer
343 ; CHECK-NEXT: ret <2 x i32> [[M]]
345 %x = mul <2 x i32> %px, %px ; thwart complexity-based canonicalization
346 %z = zext <2 x i1> %y to <2 x i32>
347 %m = mul <2 x i32> %x, %z
351 ; X * C (when X is a sext boolean) --> X ? -C : 0
353 define i32 @mul_sext_bool(i1 %x) {
354 ; CHECK-LABEL: @mul_sext_bool(
355 ; CHECK-NEXT: [[M:%.*]] = select i1 [[X:%.*]], i32 -42, i32 0
356 ; CHECK-NEXT: ret i32 [[M]]
358 %s = sext i1 %x to i32
363 define i32 @mul_sext_bool_use(i1 %x) {
364 ; CHECK-LABEL: @mul_sext_bool_use(
365 ; CHECK-NEXT: [[S:%.*]] = sext i1 [[X:%.*]] to i32
366 ; CHECK-NEXT: call void @use32(i32 [[S]])
367 ; CHECK-NEXT: [[M:%.*]] = select i1 [[X]], i32 -42, i32 0
368 ; CHECK-NEXT: ret i32 [[M]]
370 %s = sext i1 %x to i32
371 call void @use32(i32 %s)
376 define <2 x i8> @mul_sext_bool_vec(<2 x i1> %x) {
377 ; CHECK-LABEL: @mul_sext_bool_vec(
378 ; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[X:%.*]], <2 x i8> <i8 -42, i8 -128>, <2 x i8> zeroinitializer
379 ; CHECK-NEXT: ret <2 x i8> [[M]]
381 %s = sext <2 x i1> %x to <2 x i8>
382 %m = mul <2 x i8> %s, <i8 42, i8 -128>
386 define <3 x i7> @mul_bools(<3 x i1> %x, <3 x i1> %y) {
387 ; CHECK-LABEL: @mul_bools(
388 ; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]]
389 ; CHECK-NEXT: [[R:%.*]] = zext <3 x i1> [[MULBOOL]] to <3 x i7>
390 ; CHECK-NEXT: ret <3 x i7> [[R]]
392 %zx = zext <3 x i1> %x to <3 x i7>
393 %zy = zext <3 x i1> %y to <3 x i7>
394 %r = mul <3 x i7> %zx, %zy
398 define i32 @mul_bools_use1(i1 %x, i1 %y) {
399 ; CHECK-LABEL: @mul_bools_use1(
400 ; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32
401 ; CHECK-NEXT: call void @use32(i32 [[ZY]])
402 ; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]]
403 ; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32
404 ; CHECK-NEXT: ret i32 [[R]]
406 %zx = zext i1 %x to i32
407 %zy = zext i1 %y to i32
408 call void @use32(i32 %zy)
409 %r = mul i32 %zx, %zy
413 define i32 @mul_bools_use2(i1 %x, i1 %y) {
414 ; CHECK-LABEL: @mul_bools_use2(
415 ; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32
416 ; CHECK-NEXT: call void @use32(i32 [[ZY]])
417 ; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]]
418 ; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32
419 ; CHECK-NEXT: ret i32 [[R]]
421 %zx = zext i1 %x to i32
422 %zy = zext i1 %y to i32
423 call void @use32(i32 %zy)
424 %r = mul i32 %zy, %zx
428 define i32 @mul_bools_use3(i1 %x, i1 %y) {
429 ; CHECK-LABEL: @mul_bools_use3(
430 ; CHECK-NEXT: [[ZX:%.*]] = zext i1 [[X:%.*]] to i32
431 ; CHECK-NEXT: call void @use32(i32 [[ZX]])
432 ; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32
433 ; CHECK-NEXT: call void @use32(i32 [[ZY]])
434 ; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i32 [[ZY]], i32 0
435 ; CHECK-NEXT: ret i32 [[R]]
437 %zx = zext i1 %x to i32
438 call void @use32(i32 %zx)
439 %zy = zext i1 %y to i32
440 call void @use32(i32 %zy)
441 %r = mul i32 %zx, %zy
445 define <3 x i32> @mul_bools_sext(<3 x i1> %x, <3 x i1> %y) {
446 ; CHECK-LABEL: @mul_bools_sext(
447 ; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]]
448 ; CHECK-NEXT: [[R:%.*]] = zext <3 x i1> [[MULBOOL]] to <3 x i32>
449 ; CHECK-NEXT: ret <3 x i32> [[R]]
451 %sx = sext <3 x i1> %x to <3 x i32>
452 %sy = sext <3 x i1> %y to <3 x i32>
453 %r = mul <3 x i32> %sx, %sy
457 define i32 @mul_bools_sext_use1(i1 %x, i1 %y) {
458 ; CHECK-LABEL: @mul_bools_sext_use1(
459 ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32
460 ; CHECK-NEXT: call void @use32(i32 [[SY]])
461 ; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]]
462 ; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32
463 ; CHECK-NEXT: ret i32 [[R]]
465 %sx = sext i1 %x to i32
466 %sy = sext i1 %y to i32
467 call void @use32(i32 %sy)
468 %r = mul i32 %sx, %sy
472 define i32 @mul_bools_sext_use2(i1 %x, i1 %y) {
473 ; CHECK-LABEL: @mul_bools_sext_use2(
474 ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32
475 ; CHECK-NEXT: call void @use32(i32 [[SY]])
476 ; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]]
477 ; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32
478 ; CHECK-NEXT: ret i32 [[R]]
480 %sx = sext i1 %x to i32
481 %sy = sext i1 %y to i32
482 call void @use32(i32 %sy)
483 %r = mul i32 %sy, %sx
487 define i32 @mul_bools_sext_use3(i1 %x, i1 %y) {
488 ; CHECK-LABEL: @mul_bools_sext_use3(
489 ; CHECK-NEXT: [[SX:%.*]] = sext i1 [[X:%.*]] to i32
490 ; CHECK-NEXT: call void @use32(i32 [[SX]])
491 ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32
492 ; CHECK-NEXT: call void @use32(i32 [[SY]])
493 ; CHECK-NEXT: [[R:%.*]] = mul nsw i32 [[SY]], [[SX]]
494 ; CHECK-NEXT: ret i32 [[R]]
496 %sx = sext i1 %x to i32
497 call void @use32(i32 %sx)
498 %sy = sext i1 %y to i32
499 call void @use32(i32 %sy)
500 %r = mul i32 %sy, %sx
504 define i32 @mul_bools_sext_one_use_per_op(i1 %x, i1 %y) {
505 ; CHECK-LABEL: @mul_bools_sext_one_use_per_op(
506 ; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y:%.*]]
507 ; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32
508 ; CHECK-NEXT: ret i32 [[R]]
510 %sx = sext i1 %x to i32
511 %sy = sext i1 %y to i32
512 %r = mul i32 %sx, %sy
516 define i32 @mul_bool_sext_one_user(i1 %x) {
517 ; CHECK-LABEL: @mul_bool_sext_one_user(
518 ; CHECK-NEXT: [[R:%.*]] = zext i1 [[X:%.*]] to i32
519 ; CHECK-NEXT: ret i32 [[R]]
521 %sx = sext i1 %x to i32
522 %r = mul i32 %sx, %sx
526 define i32 @mul_bools_zext_one_use_per_op(i1 %x, i1 %y) {
527 ; CHECK-LABEL: @mul_bools_zext_one_use_per_op(
528 ; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y:%.*]]
529 ; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32
530 ; CHECK-NEXT: ret i32 [[R]]
532 %zx = zext i1 %x to i32
533 %zy = zext i1 %y to i32
534 %r = mul i32 %zx, %zy
538 define i32 @mul_bool_zext_one_user(i1 %x) {
539 ; CHECK-LABEL: @mul_bool_zext_one_user(
540 ; CHECK-NEXT: [[R:%.*]] = zext i1 [[X:%.*]] to i32
541 ; CHECK-NEXT: ret i32 [[R]]
543 %sx = zext i1 %x to i32
544 %r = mul i32 %sx, %sx
548 define i32 @mul_bool_sext_one_extra_user(i1 %x) {
549 ; CHECK-LABEL: @mul_bool_sext_one_extra_user(
550 ; CHECK-NEXT: [[SX:%.*]] = sext i1 [[X:%.*]] to i32
551 ; CHECK-NEXT: call void @use32(i32 [[SX]])
552 ; CHECK-NEXT: [[R:%.*]] = zext i1 [[X]] to i32
553 ; CHECK-NEXT: ret i32 [[R]]
555 %sx = sext i1 %x to i32
556 call void @use32(i32 %sx)
557 %r = mul i32 %sx, %sx
561 define i32 @mul_bool_zext_one_extra_user(i1 %x) {
562 ; CHECK-LABEL: @mul_bool_zext_one_extra_user(
563 ; CHECK-NEXT: [[SX:%.*]] = zext i1 [[X:%.*]] to i32
564 ; CHECK-NEXT: call void @use32(i32 [[SX]])
565 ; CHECK-NEXT: [[R:%.*]] = zext i1 [[X]] to i32
566 ; CHECK-NEXT: ret i32 [[R]]
568 %sx = zext i1 %x to i32
569 call void @use32(i32 %sx)
570 %r = mul i32 %sx, %sx
574 define <3 x i32> @mul_bools_mixed_ext(<3 x i1> %x, <3 x i1> %y) {
575 ; CHECK-LABEL: @mul_bools_mixed_ext(
576 ; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]]
577 ; CHECK-NEXT: [[R:%.*]] = sext <3 x i1> [[MULBOOL]] to <3 x i32>
578 ; CHECK-NEXT: ret <3 x i32> [[R]]
580 %zx = zext <3 x i1> %x to <3 x i32>
581 %sy = sext <3 x i1> %y to <3 x i32>
582 %r = mul <3 x i32> %zx, %sy
586 define i32 @mul_bools_mixed_ext_use1(i1 %x, i1 %y) {
587 ; CHECK-LABEL: @mul_bools_mixed_ext_use1(
588 ; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32
589 ; CHECK-NEXT: call void @use32(i32 [[ZY]])
590 ; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]]
591 ; CHECK-NEXT: [[R:%.*]] = sext i1 [[MULBOOL]] to i32
592 ; CHECK-NEXT: ret i32 [[R]]
594 %sx = sext i1 %x to i32
595 %zy = zext i1 %y to i32
596 call void @use32(i32 %zy)
597 %r = mul i32 %sx, %zy
601 define i32 @mul_bools_mixed_ext_use2(i1 %x, i1 %y) {
602 ; CHECK-LABEL: @mul_bools_mixed_ext_use2(
603 ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32
604 ; CHECK-NEXT: call void @use32(i32 [[SY]])
605 ; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]]
606 ; CHECK-NEXT: [[R:%.*]] = sext i1 [[MULBOOL]] to i32
607 ; CHECK-NEXT: ret i32 [[R]]
609 %zx = zext i1 %x to i32
610 %sy = sext i1 %y to i32
611 call void @use32(i32 %sy)
612 %r = mul i32 %sy, %zx
616 define i32 @mul_bools_mixed_ext_use3(i1 %x, i1 %y) {
617 ; CHECK-LABEL: @mul_bools_mixed_ext_use3(
618 ; CHECK-NEXT: [[SX:%.*]] = sext i1 [[X:%.*]] to i32
619 ; CHECK-NEXT: call void @use32(i32 [[SX]])
620 ; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32
621 ; CHECK-NEXT: call void @use32(i32 [[ZY]])
622 ; CHECK-NEXT: [[R:%.*]] = select i1 [[Y]], i32 [[SX]], i32 0
623 ; CHECK-NEXT: ret i32 [[R]]
625 %sx = sext i1 %x to i32
626 call void @use32(i32 %sx)
627 %zy = zext i1 %y to i32
628 call void @use32(i32 %zy)
629 %r = mul i32 %zy, %sx
633 ; (A >>u 31) * B --> (A >>s 31) & B --> A < 0 ? B : 0
635 define i32 @signbit_mul(i32 %a, i32 %b) {
636 ; CHECK-LABEL: @signbit_mul(
637 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A:%.*]], 0
638 ; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 0
639 ; CHECK-NEXT: ret i32 [[E]]
646 define i32 @signbit_mul_commute_extra_use(i32 %a, i32 %b) {
647 ; CHECK-LABEL: @signbit_mul_commute_extra_use(
648 ; CHECK-NEXT: [[D:%.*]] = lshr i32 [[A:%.*]], 31
649 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A]], 0
650 ; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 0
651 ; CHECK-NEXT: call void @use32(i32 [[D]])
652 ; CHECK-NEXT: ret i32 [[E]]
656 call void @use32(i32 %d)
660 ; (A >>u 31)) * B --> (A >>s 31) & B --> A < 0 ? B : 0
662 define <2 x i32> @signbit_mul_vec(<2 x i32> %a, <2 x i32> %b) {
663 ; CHECK-LABEL: @signbit_mul_vec(
664 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[A:%.*]], zeroinitializer
665 ; CHECK-NEXT: [[E:%.*]] = select <2 x i1> [[ISNEG]], <2 x i32> [[B:%.*]], <2 x i32> zeroinitializer
666 ; CHECK-NEXT: ret <2 x i32> [[E]]
668 %d = lshr <2 x i32> %a, <i32 31, i32 31>
669 %e = mul <2 x i32> %d, %b
673 define <2 x i32> @signbit_mul_vec_commute(<2 x i32> %a, <2 x i32> %b) {
674 ; CHECK-LABEL: @signbit_mul_vec_commute(
675 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[A:%.*]], zeroinitializer
676 ; CHECK-NEXT: [[E:%.*]] = select <2 x i1> [[ISNEG]], <2 x i32> [[B:%.*]], <2 x i32> zeroinitializer
677 ; CHECK-NEXT: ret <2 x i32> [[E]]
679 %d = lshr <2 x i32> %a, <i32 31, i32 31>
680 %e = mul <2 x i32> %b, %d
684 ; (A & 1) * B --> (lowbit A) ? B : 0
686 define i32 @lowbit_mul(i32 %a, i32 %b) {
687 ; CHECK-LABEL: @lowbit_mul(
688 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[A:%.*]] to i1
689 ; CHECK-NEXT: [[E:%.*]] = select i1 [[TMP1]], i32 [[B:%.*]], i32 0
690 ; CHECK-NEXT: ret i32 [[E]]
697 ; (A & 1) * B --> (lowbit A) ? B : 0
699 define <2 x i17> @lowbit_mul_commute(<2 x i17> %a, <2 x i17> %p) {
700 ; CHECK-LABEL: @lowbit_mul_commute(
701 ; CHECK-NEXT: [[B:%.*]] = xor <2 x i17> [[P:%.*]], <i17 42, i17 43>
702 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i17> [[A:%.*]] to <2 x i1>
703 ; CHECK-NEXT: [[E:%.*]] = select <2 x i1> [[TMP1]], <2 x i17> [[B]], <2 x i17> zeroinitializer
704 ; CHECK-NEXT: ret <2 x i17> [[E]]
706 %b = xor <2 x i17> %p, <i17 42, i17 43> ; thwart complexity-based canonicalization
707 %d = and <2 x i17> %a, <i17 1, i17 1>
708 %e = mul <2 x i17> %b, %d
712 ; negative test - extra use
714 define i32 @lowbit_mul_use(i32 %a, i32 %b) {
715 ; CHECK-LABEL: @lowbit_mul_use(
716 ; CHECK-NEXT: [[D:%.*]] = and i32 [[A:%.*]], 1
717 ; CHECK-NEXT: call void @use32(i32 [[D]])
718 ; CHECK-NEXT: [[E:%.*]] = mul nuw i32 [[D]], [[B:%.*]]
719 ; CHECK-NEXT: ret i32 [[E]]
722 call void @use32(i32 %d)
727 ; negative test - wrong mask
729 define i32 @not_lowbit_mul(i32 %a, i32 %b) {
730 ; CHECK-LABEL: @not_lowbit_mul(
731 ; CHECK-NEXT: [[D:%.*]] = and i32 [[A:%.*]], 2
732 ; CHECK-NEXT: [[E:%.*]] = mul i32 [[D]], [[B:%.*]]
733 ; CHECK-NEXT: ret i32 [[E]]
740 define i32 @signsplat_mul(i32 %x) {
741 ; CHECK-LABEL: @signsplat_mul(
742 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[X:%.*]], 0
743 ; CHECK-NEXT: [[MUL:%.*]] = select i1 [[ISNEG]], i32 -42, i32 0
744 ; CHECK-NEXT: ret i32 [[MUL]]
746 %ash = ashr i32 %x, 31
747 %mul = mul i32 %ash, 42
751 define <2 x i32> @signsplat_mul_vec(<2 x i32> %x) {
752 ; CHECK-LABEL: @signsplat_mul_vec(
753 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[X:%.*]], zeroinitializer
754 ; CHECK-NEXT: [[MUL:%.*]] = select <2 x i1> [[ISNEG]], <2 x i32> <i32 -42, i32 3>, <2 x i32> zeroinitializer
755 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
757 %ash = ashr <2 x i32> %x, <i32 31, i32 31>
758 %mul = mul <2 x i32> %ash, <i32 42, i32 -3>
762 ; negative test - wrong shift amount
764 define i32 @not_signsplat_mul(i32 %x) {
765 ; CHECK-LABEL: @not_signsplat_mul(
766 ; CHECK-NEXT: [[ASH:%.*]] = ashr i32 [[X:%.*]], 30
767 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ASH]], 42
768 ; CHECK-NEXT: ret i32 [[MUL]]
770 %ash = ashr i32 %x, 30
771 %mul = mul i32 %ash, 42
775 ; negative test - extra use
777 define i32 @signsplat_mul_use(i32 %x) {
778 ; CHECK-LABEL: @signsplat_mul_use(
779 ; CHECK-NEXT: [[ASH:%.*]] = ashr i32 [[X:%.*]], 31
780 ; CHECK-NEXT: call void @use32(i32 [[ASH]])
781 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ASH]], -42
782 ; CHECK-NEXT: ret i32 [[MUL]]
784 %ash = ashr i32 %x, 31
785 call void @use32(i32 %ash)
786 %mul = mul i32 %ash, -42
790 define i32 @test18(i32 %A, i32 %B) {
791 ; CHECK-LABEL: @test18(
792 ; CHECK-NEXT: ret i32 0
801 declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32)
802 declare void @use(i1)
804 define i32 @test19(i32 %A, i32 %B) {
805 ; CHECK-LABEL: @test19(
806 ; CHECK-NEXT: call void @use(i1 false)
807 ; CHECK-NEXT: ret i32 0
812 ; It would be nice if we also started proving that this doesn't overflow.
813 %E = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %C, i32 %D)
814 %F = extractvalue {i32, i1} %E, 0
815 %G = extractvalue {i32, i1} %E, 1
816 call void @use(i1 %G)
821 define <2 x i64> @test20(<2 x i64> %A) {
822 ; CHECK-LABEL: @test20(
823 ; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i64> [[A:%.*]], <i64 3, i64 2>
824 ; CHECK-NEXT: [[C:%.*]] = add <2 x i64> [[TMP1]], <i64 36, i64 28>
825 ; CHECK-NEXT: ret <2 x i64> [[C]]
827 %B = add <2 x i64> %A, <i64 12, i64 14>
828 %C = mul <2 x i64> %B, <i64 3, i64 2>
832 @g = internal global i32 0, align 4
834 define i32 @PR20079(i32 %a) {
835 ; CHECK-LABEL: @PR20079(
836 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A:%.*]], -1
837 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ADD]], ptrtoint (ptr @g to i32)
838 ; CHECK-NEXT: ret i32 [[MUL]]
840 %add = add i32 %a, -1
841 %mul = mul nsw i32 %add, ptrtoint (ptr @g to i32)
845 ; Keep nuw flag in this change, https://alive2.llvm.org/ce/z/-Wowpk
846 define i32 @add_mul_nuw(i32 %a) {
847 ; CHECK-LABEL: @add_mul_nuw(
848 ; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i32 [[A:%.*]], 3
849 ; CHECK-NEXT: [[MUL:%.*]] = add nuw i32 [[TMP1]], 9
850 ; CHECK-NEXT: ret i32 [[MUL]]
852 %add = add nuw i32 %a, 3
853 %mul = mul nuw i32 %add, 3
857 ; Don't propagate nsw flag in this change
858 define i32 @add_mul_nsw(i32 %a) {
859 ; CHECK-LABEL: @add_mul_nsw(
860 ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 3
861 ; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9
862 ; CHECK-NEXT: ret i32 [[MUL]]
864 %add = add nsw i32 %a, 3
865 %mul = mul nsw i32 %add, 3
869 ; Only the add or only the mul has nuw, https://alive2.llvm.org/ce/z/vPwbEa
870 define i32 @only_add_nuw(i32 %a) {
871 ; CHECK-LABEL: @only_add_nuw(
872 ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 3
873 ; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9
874 ; CHECK-NEXT: ret i32 [[MUL]]
876 %add = add nuw i32 %a, 3
877 %mul = mul i32 %add, 3
881 define i32 @only_mul_nuw(i32 %a) {
882 ; CHECK-LABEL: @only_mul_nuw(
883 ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 3
884 ; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9
885 ; CHECK-NEXT: ret i32 [[MUL]]
888 %mul = mul nuw i32 %add, 3
892 ; Don't propagate nsw flag in this change, https://alive2.llvm.org/ce/z/jJ8rZd
893 define i32 @PR57278_shl(i32 %a) {
894 ; CHECK-LABEL: @PR57278_shl(
895 ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 12
896 ; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9
897 ; CHECK-NEXT: ret i32 [[MUL]]
899 %shl = shl nsw i32 %a, 2
900 %add = or i32 %shl, 3
901 %mul = mul nsw i32 %add, 3
905 ; Negative test: Have common bits set
906 define i32 @PR57278_shl_1(i32 %a) {
907 ; CHECK-LABEL: @PR57278_shl_1(
908 ; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[A:%.*]], 2
909 ; CHECK-NEXT: [[ADD:%.*]] = or i32 [[SHL]], 4
910 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ADD]], 3
911 ; CHECK-NEXT: ret i32 [[MUL]]
913 %shl = shl nsw i32 %a, 2
914 %add = or i32 %shl, 4
915 %mul = mul nsw i32 %add, 3
919 ; Keep nuw flag in this change, https://alive2.llvm.org/ce/z/awsQrx
920 define i32 @PR57278_mul(i32 %a) {
921 ; CHECK-LABEL: @PR57278_mul(
922 ; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i32 [[A:%.*]], 36
923 ; CHECK-NEXT: [[MUL:%.*]] = add nuw i32 [[TMP1]], 9
924 ; CHECK-NEXT: ret i32 [[MUL]]
926 %mul0 = mul nuw i32 %a, 12
927 %add = or i32 %mul0, 3
928 %mul = mul nuw i32 %add, 3
932 ; Negative test: Have common bits set, https://alive2.llvm.org/ce/z/bHZRh5
933 define i32 @PR57278_mul_1(i32 %a) {
934 ; CHECK-LABEL: @PR57278_mul_1(
935 ; CHECK-NEXT: [[MUL0:%.*]] = mul nuw i32 [[A:%.*]], 12
936 ; CHECK-NEXT: [[ADD:%.*]] = or i32 [[MUL0]], 4
937 ; CHECK-NEXT: [[MUL:%.*]] = mul nuw i32 [[ADD]], 3
938 ; CHECK-NEXT: ret i32 [[MUL]]
940 %mul0 = mul nuw i32 %a, 12
941 %add = or i32 %mul0, 4
942 %mul = mul nuw i32 %add, 3
946 ; Test the haveNoCommonBitsSet with assume, https://alive2.llvm.org/ce/z/AXKBjK
947 define i32 @PR57278_mul_assume(i32 %a) {
948 ; CHECK-LABEL: @PR57278_mul_assume(
949 ; CHECK-NEXT: [[COMBITS:%.*]] = and i32 [[A:%.*]], 3
950 ; CHECK-NEXT: [[NOCOMBITS:%.*]] = icmp eq i32 [[COMBITS]], 0
951 ; CHECK-NEXT: call void @llvm.assume(i1 [[NOCOMBITS]])
952 ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A]], 5
953 ; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 15
954 ; CHECK-NEXT: ret i32 [[MUL]]
956 %combits = and i32 %a , 3
957 %nocombits = icmp eq i32 %combits, 0
958 call void @llvm.assume(i1 %nocombits)
961 %mul = mul i32 %add, 5
965 declare void @llvm.assume(i1)
967 define i32 @PR57278_or_disjoint_nuw(i32 %a) {
968 ; CHECK-LABEL: @PR57278_or_disjoint_nuw(
969 ; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i32 [[A:%.*]], 3
970 ; CHECK-NEXT: [[MUL:%.*]] = add nuw i32 [[TMP1]], 9
971 ; CHECK-NEXT: ret i32 [[MUL]]
973 %add = or disjoint i32 %a, 3
974 %mul = mul nuw i32 %add, 3
978 define i32 @PR57278_or_disjoint_nsw(i32 %a) {
979 ; CHECK-LABEL: @PR57278_or_disjoint_nsw(
980 ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 3
981 ; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9
982 ; CHECK-NEXT: ret i32 [[MUL]]
984 %add = or disjoint i32 %a, 3
985 %mul = mul nsw i32 %add, 3
989 ; https://alive2.llvm.org/ce/z/XYpv9q
990 define <2 x i32> @PR57278_shl_vec(<2 x i32> %v1) {
991 ; CHECK-LABEL: @PR57278_shl_vec(
992 ; CHECK-NEXT: [[TMP1:%.*]] = mul nuw <2 x i32> [[V1:%.*]], <i32 12, i32 24>
993 ; CHECK-NEXT: [[MUL:%.*]] = add nuw <2 x i32> [[TMP1]], splat (i32 9)
994 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
996 %shl = shl nuw <2 x i32> %v1, <i32 2, i32 3>
997 %add = or <2 x i32> %shl, <i32 3, i32 3>
998 %mul = mul nuw <2 x i32> %add, <i32 3, i32 3>
1002 ; TODO: vector with poison should also be supported, https://alive2.llvm.org/ce/z/XYpv9q
1003 define <2 x i32> @PR57278_shl_vec_poison(<2 x i32> %v1) {
1004 ; CHECK-LABEL: @PR57278_shl_vec_poison(
1005 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw <2 x i32> [[V1:%.*]], <i32 2, i32 poison>
1006 ; CHECK-NEXT: [[TMP1:%.*]] = mul nuw <2 x i32> [[SHL]], <i32 3, i32 poison>
1007 ; CHECK-NEXT: [[MUL:%.*]] = add nuw <2 x i32> [[TMP1]], <i32 9, i32 poison>
1008 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1010 %shl = shl nuw <2 x i32> %v1, <i32 2, i32 poison>
1011 %add = or <2 x i32> %shl, <i32 3, i32 poison>
1012 %mul = mul nuw <2 x i32> %add, <i32 3, i32 poison>
1016 define <2 x i1> @test21(<2 x i1> %A, <2 x i1> %B) {
1017 ; CHECK-LABEL: @test21(
1018 ; CHECK-NEXT: [[C:%.*]] = and <2 x i1> [[A:%.*]], [[B:%.*]]
1019 ; CHECK-NEXT: ret <2 x i1> [[C]]
1021 %C = mul <2 x i1> %A, %B
1025 define i32 @test22(i32 %A) {
1026 ; CHECK-LABEL: @test22(
1027 ; CHECK-NEXT: [[B:%.*]] = sub nsw i32 0, [[A:%.*]]
1028 ; CHECK-NEXT: ret i32 [[B]]
1030 %B = mul nsw i32 %A, -1
1034 define i32 @test23(i32 %A) {
1035 ; CHECK-LABEL: @test23(
1036 ; CHECK-NEXT: [[C:%.*]] = mul nuw i32 [[A:%.*]], 6
1037 ; CHECK-NEXT: ret i32 [[C]]
1039 %B = shl nuw i32 %A, 1
1040 %C = mul nuw i32 %B, 3
1044 define i32 @test24(i32 %A) {
1045 ; CHECK-LABEL: @test24(
1046 ; CHECK-NEXT: [[C:%.*]] = mul nsw i32 [[A:%.*]], 6
1047 ; CHECK-NEXT: ret i32 [[C]]
1049 %B = shl nsw i32 %A, 1
1050 %C = mul nsw i32 %B, 3
1054 define i32 @neg_neg_mul(i32 %A, i32 %B) {
1055 ; CHECK-LABEL: @neg_neg_mul(
1056 ; CHECK-NEXT: [[E:%.*]] = mul i32 [[A:%.*]], [[B:%.*]]
1057 ; CHECK-NEXT: ret i32 [[E]]
1065 define i32 @neg_neg_mul_nsw(i32 %A, i32 %B) {
1066 ; CHECK-LABEL: @neg_neg_mul_nsw(
1067 ; CHECK-NEXT: [[E:%.*]] = mul nsw i32 [[A:%.*]], [[B:%.*]]
1068 ; CHECK-NEXT: ret i32 [[E]]
1070 %C = sub nsw i32 0, %A
1071 %D = sub nsw i32 0, %B
1072 %E = mul nsw i32 %C, %D
1076 define i124 @neg_neg_mul_apint(i124 %A, i124 %B) {
1077 ; CHECK-LABEL: @neg_neg_mul_apint(
1078 ; CHECK-NEXT: [[E:%.*]] = mul i124 [[A:%.*]], [[B:%.*]]
1079 ; CHECK-NEXT: ret i124 [[E]]
1083 %E = mul i124 %C, %D
1087 define i32 @neg_mul_constant(i32 %A) {
1088 ; CHECK-LABEL: @neg_mul_constant(
1089 ; CHECK-NEXT: [[E:%.*]] = mul i32 [[A:%.*]], -7
1090 ; CHECK-NEXT: ret i32 [[E]]
1097 define i55 @neg_mul_constant_apint(i55 %A) {
1098 ; CHECK-LABEL: @neg_mul_constant_apint(
1099 ; CHECK-NEXT: [[E:%.*]] = mul i55 [[A:%.*]], -7
1100 ; CHECK-NEXT: ret i55 [[E]]
1107 define <3 x i8> @neg_mul_constant_vec(<3 x i8> %a) {
1108 ; CHECK-LABEL: @neg_mul_constant_vec(
1109 ; CHECK-NEXT: [[B:%.*]] = mul <3 x i8> [[A:%.*]], splat (i8 -5)
1110 ; CHECK-NEXT: ret <3 x i8> [[B]]
1112 %A = sub <3 x i8> zeroinitializer, %a
1113 %B = mul <3 x i8> %A, <i8 5, i8 5, i8 5>
1117 define <3 x i4> @neg_mul_constant_vec_weird(<3 x i4> %a) {
1118 ; CHECK-LABEL: @neg_mul_constant_vec_weird(
1119 ; CHECK-NEXT: [[B:%.*]] = mul <3 x i4> [[A:%.*]], splat (i4 -5)
1120 ; CHECK-NEXT: ret <3 x i4> [[B]]
1122 %A = sub <3 x i4> zeroinitializer, %a
1123 %B = mul <3 x i4> %A, <i4 5, i4 5, i4 5>
1127 define i64 @test29(i31 %A, i31 %B) {
1128 ; CHECK-LABEL: @test29(
1129 ; CHECK-NEXT: [[C:%.*]] = sext i31 [[A:%.*]] to i64
1130 ; CHECK-NEXT: [[D:%.*]] = sext i31 [[B:%.*]] to i64
1131 ; CHECK-NEXT: [[E:%.*]] = mul nsw i64 [[C]], [[D]]
1132 ; CHECK-NEXT: ret i64 [[E]]
1134 %C = sext i31 %A to i64
1135 %D = sext i31 %B to i64
1140 define i64 @test30(i32 %A, i32 %B) {
1141 ; CHECK-LABEL: @test30(
1142 ; CHECK-NEXT: [[C:%.*]] = zext i32 [[A:%.*]] to i64
1143 ; CHECK-NEXT: [[D:%.*]] = zext i32 [[B:%.*]] to i64
1144 ; CHECK-NEXT: [[E:%.*]] = mul nuw i64 [[C]], [[D]]
1145 ; CHECK-NEXT: ret i64 [[E]]
1147 %C = zext i32 %A to i64
1148 %D = zext i32 %B to i64
1153 @PR22087 = external global i32
1154 define i32 @test31(i32 %V) {
1155 ; CHECK-LABEL: @test31(
1156 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr inttoptr (i64 4 to ptr), @PR22087
1157 ; CHECK-NEXT: [[EXT:%.*]] = zext i1 [[CMP]] to i32
1158 ; CHECK-NEXT: [[MUL1:%.*]] = shl i32 [[V:%.*]], [[EXT]]
1159 ; CHECK-NEXT: ret i32 [[MUL1]]
1161 %cmp = icmp ne ptr inttoptr (i64 4 to ptr), @PR22087
1162 %ext = zext i1 %cmp to i32
1163 %shl = shl i32 1, %ext
1164 %mul = mul i32 %V, %shl
1168 define i32 @test32(i32 %X) {
1169 ; CHECK-LABEL: @test32(
1170 ; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[X:%.*]], 31
1171 ; CHECK-NEXT: ret i32 [[MUL]]
1173 %mul = mul nsw i32 %X, -2147483648
1177 define <2 x i32> @test32vec(<2 x i32> %X) {
1178 ; CHECK-LABEL: @test32vec(
1179 ; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[X:%.*]], splat (i32 31)
1180 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1182 %mul = mul nsw <2 x i32> %X, <i32 -2147483648, i32 -2147483648>
1186 define i32 @test33(i32 %X) {
1187 ; CHECK-LABEL: @test33(
1188 ; CHECK-NEXT: [[MUL:%.*]] = shl nsw i32 [[X:%.*]], 30
1189 ; CHECK-NEXT: ret i32 [[MUL]]
1191 %mul = mul nsw i32 %X, 1073741824
1195 define <2 x i32> @test33vec(<2 x i32> %X) {
1196 ; CHECK-LABEL: @test33vec(
1197 ; CHECK-NEXT: [[MUL:%.*]] = shl nsw <2 x i32> [[X:%.*]], splat (i32 30)
1198 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1200 %mul = mul nsw <2 x i32> %X, <i32 1073741824, i32 1073741824>
1204 define i128 @test34(i128 %X) {
1205 ; CHECK-LABEL: @test34(
1206 ; CHECK-NEXT: [[MUL:%.*]] = shl nsw i128 [[X:%.*]], 1
1207 ; CHECK-NEXT: ret i128 [[MUL]]
1209 %mul = mul nsw i128 %X, 2
1213 define i32 @test_mul_canonicalize_op0(i32 %x, i32 %y) {
1214 ; CHECK-LABEL: @test_mul_canonicalize_op0(
1215 ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]
1216 ; CHECK-NEXT: [[MUL:%.*]] = sub i32 0, [[TMP1]]
1217 ; CHECK-NEXT: ret i32 [[MUL]]
1219 %neg = sub i32 0, %x
1220 %mul = mul i32 %neg, %y
1224 define i32 @test_mul_canonicalize_op1(i32 %x, i32 %z) {
1225 ; CHECK-LABEL: @test_mul_canonicalize_op1(
1226 ; CHECK-NEXT: [[Y_NEG:%.*]] = mul i32 [[Z:%.*]], -3
1227 ; CHECK-NEXT: [[DOTNEG:%.*]] = mul i32 [[Y_NEG]], [[X:%.*]]
1228 ; CHECK-NEXT: ret i32 [[DOTNEG]]
1231 %neg = sub i32 0, %x
1232 %mul = mul i32 %y, %neg
1236 define i32 @test_mul_canonicalize_nsw(i32 %x, i32 %y) {
1237 ; CHECK-LABEL: @test_mul_canonicalize_nsw(
1238 ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]
1239 ; CHECK-NEXT: [[MUL:%.*]] = sub i32 0, [[TMP1]]
1240 ; CHECK-NEXT: ret i32 [[MUL]]
1242 %neg = sub nsw i32 0, %x
1243 %mul = mul nsw i32 %neg, %y
1247 define <2 x i32> @test_mul_canonicalize_vec(<2 x i32> %x, <2 x i32> %y) {
1248 ; CHECK-LABEL: @test_mul_canonicalize_vec(
1249 ; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[X:%.*]], [[Y:%.*]]
1250 ; CHECK-NEXT: [[MUL:%.*]] = sub <2 x i32> zeroinitializer, [[TMP1]]
1251 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1253 %neg = sub <2 x i32> <i32 0, i32 0>, %x
1254 %mul = mul <2 x i32> %neg, %y
1258 define i32 @test_mul_canonicalize_multiple_uses(i32 %x, i32 %y) {
1259 ; CHECK-LABEL: @test_mul_canonicalize_multiple_uses(
1260 ; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]
1261 ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]]
1262 ; CHECK-NEXT: ret i32 [[MUL2]]
1264 %neg = sub i32 0, %x
1265 %mul = mul i32 %neg, %y
1266 %mul2 = mul i32 %mul, %neg
1270 define i32 @mul_nsw_mul_nsw_neg(i32 %x, i32 %y) {
1271 ; CHECK-LABEL: @mul_nsw_mul_nsw_neg(
1272 ; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]
1273 ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]]
1274 ; CHECK-NEXT: ret i32 [[MUL2]]
1276 %neg = sub i32 0, %x
1277 %mul = mul nsw i32 %neg, %y
1278 %mul2 = mul nsw i32 %mul, %neg
1282 define i32 @mul_mul_nsw_neg(i32 %x,i32 %y) {
1283 ; CHECK-LABEL: @mul_mul_nsw_neg(
1284 ; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]
1285 ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]]
1286 ; CHECK-NEXT: ret i32 [[MUL2]]
1288 %neg = sub i32 0, %x
1289 %mul = mul nsw i32 %neg, %y
1290 %mul2 = mul i32 %mul, %neg
1294 define i32 @mul_nsw_mul_neg(i32 %x,i32 %y) {
1295 ; CHECK-LABEL: @mul_nsw_mul_neg(
1296 ; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]
1297 ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]]
1298 ; CHECK-NEXT: ret i32 [[MUL2]]
1300 %neg = sub i32 0, %x
1301 %mul = mul i32 %neg, %y
1302 %mul2 = mul nsw i32 %mul, %neg
1306 define i32 @mul_nsw_mul_neg_onearg(i32 %x) {
1307 ; CHECK-LABEL: @mul_nsw_mul_neg_onearg(
1308 ; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[X]]
1309 ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]]
1310 ; CHECK-NEXT: ret i32 [[MUL2]]
1312 %neg = sub i32 0, %x
1313 %mul = mul i32 %neg, %x
1314 %mul2 = mul nsw i32 %mul, %neg
1318 define i8 @mul_mul_nsw_neg_onearg(i8 %x) {
1319 ; CHECK-LABEL: @mul_mul_nsw_neg_onearg(
1320 ; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i8 [[X:%.*]], [[X]]
1321 ; CHECK-NEXT: [[MUL2:%.*]] = mul i8 [[MUL_NEG]], [[X]]
1322 ; CHECK-NEXT: ret i8 [[MUL2]]
1325 %mul = mul nsw i8 %neg, %x
1326 %mul2 = mul i8 %mul, %neg
1330 define i32 @mul_nsw_mul_nsw_neg_onearg(i32 %x) {
1331 ; CHECK-LABEL: @mul_nsw_mul_nsw_neg_onearg(
1332 ; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[X]]
1333 ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]]
1334 ; CHECK-NEXT: ret i32 [[MUL2]]
1336 %neg = sub i32 0, %x
1337 %mul = mul nsw i32 %neg, %x
1338 %mul2 = mul nsw i32 %mul, %neg
1342 define i32 @mul_nsw_shl_nsw_neg(i32 %x, i32 %y) {
1343 ; CHECK-LABEL: @mul_nsw_shl_nsw_neg(
1344 ; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
1345 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]]
1346 ; CHECK-NEXT: ret i32 [[MUL]]
1348 %neg = sub i32 0, %x
1349 %shl = shl nsw i32 %neg, %y
1350 %mul = mul nsw i32 %shl, %neg
1354 define i32 @mul_shl_nsw_neg(i32 %x,i32 %y) {
1355 ; CHECK-LABEL: @mul_shl_nsw_neg(
1356 ; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
1357 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]]
1358 ; CHECK-NEXT: ret i32 [[MUL]]
1360 %neg = sub i32 0, %x
1361 %shl = shl nsw i32 %neg, %y
1362 %mul = mul i32 %shl, %neg
1366 define i32 @mul_nsw_shl_neg(i32 %x,i32 %y) {
1367 ; CHECK-LABEL: @mul_nsw_shl_neg(
1368 ; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
1369 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]]
1370 ; CHECK-NEXT: ret i32 [[MUL]]
1372 %neg = sub i32 0, %x
1373 %shl = shl i32 %neg, %y
1374 %mul = mul nsw i32 %shl, %neg
1378 define i32 @mul_nsw_shl_neg_onearg(i32 %x) {
1379 ; CHECK-LABEL: @mul_nsw_shl_neg_onearg(
1380 ; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 [[X:%.*]], [[X]]
1381 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]]
1382 ; CHECK-NEXT: ret i32 [[MUL]]
1384 %neg = sub i32 0, %x
1385 %shl = shl i32 %neg, %x
1386 %mul = mul nsw i32 %shl, %neg
1390 define i8 @mul_shl_nsw_neg_onearg(i8 %x) {
1391 ; CHECK-LABEL: @mul_shl_nsw_neg_onearg(
1392 ; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i8 [[X:%.*]], [[X]]
1393 ; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[SHL_NEG]], [[X]]
1394 ; CHECK-NEXT: ret i8 [[MUL]]
1397 %shl = shl nsw i8 %neg, %x
1398 %mul = mul i8 %shl, %neg
1402 define i32 @mul_nsw_shl_nsw_neg_onearg(i32 %x) {
1403 ; CHECK-LABEL: @mul_nsw_shl_nsw_neg_onearg(
1404 ; CHECK-NEXT: [[SHL_NEG:%.*]] = mul i32 [[X:%.*]], [[X]]
1405 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]]
1406 ; CHECK-NEXT: ret i32 [[MUL]]
1408 %neg = sub i32 0, %x
1409 %shl = mul nsw i32 %neg, %x
1410 %mul = mul nsw i32 %shl, %neg
1414 define i32 @mul_use_mul_neg(i32 %x,i32 %y) {
1415 ; CHECK-LABEL: @mul_use_mul_neg(
1416 ; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]]
1417 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[Y:%.*]], [[NEG]]
1418 ; CHECK-NEXT: call void @use32(i32 [[MUL]])
1419 ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL]], [[NEG]]
1420 ; CHECK-NEXT: ret i32 [[MUL2]]
1422 %neg = sub i32 0, %x
1423 %mul = mul i32 %neg, %y
1424 call void @use32(i32 %mul)
1425 %mul2 = mul i32 %mul, %neg
1429 define i32 @mul_shl_use_mul_neg(i32 %x,i32 %y) {
1430 ; CHECK-LABEL: @mul_shl_use_mul_neg(
1431 ; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]]
1432 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[NEG]], [[Y:%.*]]
1433 ; CHECK-NEXT: call void @use32(i32 [[SHL]])
1434 ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[SHL]], [[NEG]]
1435 ; CHECK-NEXT: ret i32 [[MUL2]]
1437 %neg = sub i32 0, %x
1438 %shl = shl i32 %neg, %y
1439 call void @use32(i32 %shl)
1440 %mul2 = mul i32 %shl, %neg
1446 define i64 @test_mul_canonicalize_neg_is_not_undone(i64 %L1) {
1447 ; Check we do not undo the canonicalization of 0 - (X * Y), if Y is a constant
1449 ; CHECK-LABEL: @test_mul_canonicalize_neg_is_not_undone(
1450 ; CHECK-NEXT: [[B4:%.*]] = mul i64 [[L1:%.*]], sub (i64 0, i64 ptrtoint (ptr @X to i64))
1451 ; CHECK-NEXT: ret i64 [[B4]]
1453 %v1 = ptrtoint ptr @X to i64
1454 %B8 = sub i64 0, %v1
1455 %B4 = mul i64 %B8, %L1
1459 define i32 @negate_if_true(i32 %x, i1 %cond) {
1460 ; CHECK-LABEL: @negate_if_true(
1461 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]]
1462 ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[X]]
1463 ; CHECK-NEXT: ret i32 [[R]]
1465 %sel = select i1 %cond, i32 -1, i32 1
1466 %r = mul i32 %sel, %x
1470 define i32 @negate_if_false(i32 %x, i1 %cond) {
1471 ; CHECK-LABEL: @negate_if_false(
1472 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]]
1473 ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND:%.*]], i32 [[X]], i32 [[TMP1]]
1474 ; CHECK-NEXT: ret i32 [[R]]
1476 %sel = select i1 %cond, i32 1, i32 -1
1477 %r = mul i32 %sel, %x
1481 define <2 x i8> @negate_if_true_commute(<2 x i8> %px, i1 %cond) {
1482 ; CHECK-LABEL: @negate_if_true_commute(
1483 ; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> splat (i8 42), [[PX:%.*]]
1484 ; CHECK-NEXT: [[TMP1:%.*]] = sub nsw <2 x i8> zeroinitializer, [[X]]
1485 ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND:%.*]], <2 x i8> [[TMP1]], <2 x i8> [[X]]
1486 ; CHECK-NEXT: ret <2 x i8> [[R]]
1488 %x = sdiv <2 x i8> <i8 42, i8 42>, %px ; thwart complexity-based canonicalization
1489 %sel = select i1 %cond, <2 x i8> <i8 -1, i8 -1>, <2 x i8> <i8 1, i8 1>
1490 %r = mul <2 x i8> %x, %sel
1494 define <2 x i8> @negate_if_false_commute(<2 x i8> %px, <2 x i1> %cond) {
1495 ; CHECK-LABEL: @negate_if_false_commute(
1496 ; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> <i8 42, i8 5>, [[PX:%.*]]
1497 ; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i8> zeroinitializer, [[X]]
1498 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i8> [[X]], <2 x i8> [[TMP1]]
1499 ; CHECK-NEXT: ret <2 x i8> [[R]]
1501 %x = sdiv <2 x i8> <i8 42, i8 5>, %px ; thwart complexity-based canonicalization
1502 %sel = select <2 x i1> %cond, <2 x i8> <i8 1, i8 poison>, <2 x i8> <i8 -1, i8 -1>
1503 %r = mul <2 x i8> %x, %sel
1509 define i32 @negate_if_true_extra_use(i32 %x, i1 %cond) {
1510 ; CHECK-LABEL: @negate_if_true_extra_use(
1511 ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 -1, i32 1
1512 ; CHECK-NEXT: call void @use32(i32 [[SEL]])
1513 ; CHECK-NEXT: [[R:%.*]] = mul i32 [[SEL]], [[X:%.*]]
1514 ; CHECK-NEXT: ret i32 [[R]]
1516 %sel = select i1 %cond, i32 -1, i32 1
1517 call void @use32(i32 %sel)
1518 %r = mul i32 %sel, %x
1524 define <2 x i8> @negate_if_true_wrong_constant(<2 x i8> %px, i1 %cond) {
1525 ; CHECK-LABEL: @negate_if_true_wrong_constant(
1526 ; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> splat (i8 42), [[PX:%.*]]
1527 ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> <i8 -1, i8 0>, <2 x i8> splat (i8 1)
1528 ; CHECK-NEXT: [[R:%.*]] = mul <2 x i8> [[X]], [[SEL]]
1529 ; CHECK-NEXT: ret <2 x i8> [[R]]
1531 %x = sdiv <2 x i8> <i8 42, i8 42>, %px ; thwart complexity-based canonicalization
1532 %sel = select i1 %cond, <2 x i8> <i8 -1, i8 0>, <2 x i8> <i8 1, i8 1>
1533 %r = mul <2 x i8> %x, %sel
1537 ; (C ? (X /exact Y) : 1) * Y -> C ? X : Y
1538 define i32 @mul_div_select(i32 %x, i32 %y, i1 %c) {
1539 ; CHECK-LABEL: @mul_div_select(
1540 ; CHECK-NEXT: [[MUL:%.*]] = select i1 [[C:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]
1541 ; CHECK-NEXT: ret i32 [[MUL]]
1543 %div = udiv exact i32 %x, %y
1544 %sel = select i1 %c, i32 %div, i32 1
1545 %mul = mul i32 %sel, %y
1549 ; fold mul(abs(x),abs(x)) -> mul(x,x)
1550 define i31 @combine_mul_abs_i31(i31 %0) {
1551 ; CHECK-LABEL: @combine_mul_abs_i31(
1552 ; CHECK-NEXT: [[M:%.*]] = mul i31 [[TMP0:%.*]], [[TMP0]]
1553 ; CHECK-NEXT: ret i31 [[M]]
1555 %c = icmp slt i31 %0, 0
1556 %s = sub nsw i31 0, %0
1557 %r = select i1 %c, i31 %s, i31 %0
1562 define i32 @combine_mul_abs_i32(i32 %0) {
1563 ; CHECK-LABEL: @combine_mul_abs_i32(
1564 ; CHECK-NEXT: [[M:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]]
1565 ; CHECK-NEXT: ret i32 [[M]]
1567 %c = icmp slt i32 %0, 0
1568 %s = sub nsw i32 0, %0
1569 %r = select i1 %c, i32 %s, i32 %0
1574 define <4 x i32> @combine_mul_abs_v4i32(<4 x i32> %0) {
1575 ; CHECK-LABEL: @combine_mul_abs_v4i32(
1576 ; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]]
1577 ; CHECK-NEXT: ret <4 x i32> [[M]]
1579 %c = icmp slt <4 x i32> %0, zeroinitializer
1580 %s = sub nsw <4 x i32> zeroinitializer, %0
1581 %r = select <4 x i1> %c, <4 x i32> %s, <4 x i32> %0
1582 %m = mul <4 x i32> %r, %r
1586 ; fold mul(nabs(x),nabs(x)) -> mul(x,x)
1587 define i31 @combine_mul_nabs_i31(i31 %0) {
1588 ; CHECK-LABEL: @combine_mul_nabs_i31(
1589 ; CHECK-NEXT: [[M:%.*]] = mul i31 [[TMP0:%.*]], [[TMP0]]
1590 ; CHECK-NEXT: ret i31 [[M]]
1592 %c = icmp slt i31 %0, 0
1593 %s = sub nsw i31 0, %0
1594 %r = select i1 %c, i31 %0, i31 %s
1599 define i32 @combine_mul_nabs_i32(i32 %0) {
1600 ; CHECK-LABEL: @combine_mul_nabs_i32(
1601 ; CHECK-NEXT: [[M:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]]
1602 ; CHECK-NEXT: ret i32 [[M]]
1604 %c = icmp slt i32 %0, 0
1605 %s = sub nsw i32 0, %0
1606 %r = select i1 %c, i32 %0, i32 %s
1611 define <4 x i32> @combine_mul_nabs_v4i32(<4 x i32> %0) {
1612 ; CHECK-LABEL: @combine_mul_nabs_v4i32(
1613 ; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]]
1614 ; CHECK-NEXT: ret <4 x i32> [[M]]
1616 %c = icmp slt <4 x i32> %0, zeroinitializer
1617 %s = sub nsw <4 x i32> zeroinitializer, %0
1618 %r = select <4 x i1> %c, <4 x i32> %0, <4 x i32> %s
1619 %m = mul <4 x i32> %r, %r
1623 define i32 @combine_mul_abs_intrin(i32 %x) {
1624 ; CHECK-LABEL: @combine_mul_abs_intrin(
1625 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]
1626 ; CHECK-NEXT: ret i32 [[MUL]]
1628 %abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
1629 %mul = mul i32 %abs, %abs
1633 define i32 @combine_mul_nabs_intrin(i32 %x) {
1634 ; CHECK-LABEL: @combine_mul_nabs_intrin(
1635 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]
1636 ; CHECK-NEXT: ret i32 [[MUL]]
1638 %abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
1639 %neg = sub i32 0, %abs
1640 %mul = mul i32 %neg, %neg
1644 ; z * splat(0) = splat(0), even for scalable vectors
1645 define <vscale x 2 x i64> @mul_scalable_splat_zero(<vscale x 2 x i64> %z) {
1646 ; CHECK-LABEL: @mul_scalable_splat_zero(
1647 ; CHECK-NEXT: ret <vscale x 2 x i64> zeroinitializer
1649 %shuf = shufflevector <vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 0, i32 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer
1650 %t3 = mul <vscale x 2 x i64> %shuf, %z
1651 ret <vscale x 2 x i64> %t3
1654 ; fold mul(abs(x),abs(y)) -> abs(mul(x,y))
1655 define i32 @combine_mul_abs_x_abs_y(i32 %x, i32 %y) {
1656 ; CHECK-LABEL: @combine_mul_abs_x_abs_y(
1657 ; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i32 [[X:%.*]], [[Y:%.*]]
1658 ; CHECK-NEXT: [[MUL:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP1]], i1 true)
1659 ; CHECK-NEXT: ret i32 [[MUL]]
1661 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)
1662 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true)
1663 %mul = mul nsw i32 %abs_x, %abs_y
1667 define i32 @combine_mul_abs_x_abs_y_no_nsw(i32 %x, i32 %y) {
1668 ; CHECK-LABEL: @combine_mul_abs_x_abs_y_no_nsw(
1669 ; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)
1670 ; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true)
1671 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[ABS_X]], [[ABS_Y]]
1672 ; CHECK-NEXT: ret i32 [[MUL]]
1674 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)
1675 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true)
1676 %mul = mul i32 %abs_x, %abs_y
1680 define i32 @combine_mul_abs_x_abs_y_poison_1(i32 %x, i32 %y) {
1681 ; CHECK-LABEL: @combine_mul_abs_x_abs_y_poison_1(
1682 ; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)
1683 ; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 false)
1684 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ABS_X]], [[ABS_Y]]
1685 ; CHECK-NEXT: ret i32 [[MUL]]
1687 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)
1688 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 false)
1689 %mul = mul nsw i32 %abs_x, %abs_y
1693 define i32 @combine_mul_abs_x_abs_y_poison_2(i32 %x, i32 %y) {
1694 ; CHECK-LABEL: @combine_mul_abs_x_abs_y_poison_2(
1695 ; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
1696 ; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 false)
1697 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ABS_X]], [[ABS_Y]]
1698 ; CHECK-NEXT: ret i32 [[MUL]]
1700 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 false)
1701 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 false)
1702 %mul = mul nsw i32 %abs_x, %abs_y
1706 define i32 @combine_mul_abs_x_abs_y_not_oneuse(i32 %x, i32 %y) {
1707 ; CHECK-LABEL: @combine_mul_abs_x_abs_y_not_oneuse(
1708 ; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)
1709 ; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true)
1710 ; CHECK-NEXT: [[ABS_X1:%.*]] = add nuw i32 [[ABS_Y]], 1
1711 ; CHECK-NEXT: [[RET:%.*]] = mul i32 [[ABS_X]], [[ABS_X1]]
1712 ; CHECK-NEXT: ret i32 [[RET]]
1714 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)
1715 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true)
1716 %mul = mul nsw i32 %abs_x, %abs_y
1717 %ret = add i32 %mul, %abs_x
1722 ; fold mul(sub(x,y),negpow2) -> shl(sub(y,x),log2(pow2))
1725 define i32 @mulsub1(i32 %a0, i32 %a1) {
1726 ; CHECK-LABEL: @mulsub1(
1727 ; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i32 [[A0:%.*]], [[A1:%.*]]
1728 ; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[SUB_NEG]], 2
1729 ; CHECK-NEXT: ret i32 [[MUL]]
1731 %sub = sub i32 %a1, %a0
1732 %mul = mul i32 %sub, -4
1736 define <2 x i32> @mulsub1_vec(<2 x i32> %a0, <2 x i32> %a1) {
1737 ; CHECK-LABEL: @mulsub1_vec(
1738 ; CHECK-NEXT: [[SUB_NEG:%.*]] = sub <2 x i32> [[A0:%.*]], [[A1:%.*]]
1739 ; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], splat (i32 2)
1740 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1742 %sub = sub <2 x i32> %a1, %a0
1743 %mul = mul <2 x i32> %sub, <i32 -4, i32 -4>
1747 define <2 x i32> @mulsub1_vec_nonuniform(<2 x i32> %a0, <2 x i32> %a1) {
1748 ; CHECK-LABEL: @mulsub1_vec_nonuniform(
1749 ; CHECK-NEXT: [[SUB_NEG:%.*]] = sub <2 x i32> [[A0:%.*]], [[A1:%.*]]
1750 ; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], <i32 2, i32 3>
1751 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1753 %sub = sub <2 x i32> %a1, %a0
1754 %mul = mul <2 x i32> %sub, <i32 -4, i32 -8>
1758 define <2 x i32> @mulsub1_vec_nonuniform_poison(<2 x i32> %a0, <2 x i32> %a1) {
1759 ; CHECK-LABEL: @mulsub1_vec_nonuniform_poison(
1760 ; CHECK-NEXT: [[SUB_NEG:%.*]] = sub <2 x i32> [[A0:%.*]], [[A1:%.*]]
1761 ; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], <i32 2, i32 0>
1762 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1764 %sub = sub <2 x i32> %a1, %a0
1765 %mul = mul <2 x i32> %sub, <i32 -4, i32 poison>
1769 define i32 @mulsub2(i32 %a0) {
1770 ; CHECK-LABEL: @mulsub2(
1771 ; CHECK-NEXT: [[SUB_NEG:%.*]] = shl i32 [[A0:%.*]], 2
1772 ; CHECK-NEXT: [[MUL:%.*]] = add i32 [[SUB_NEG]], -64
1773 ; CHECK-NEXT: ret i32 [[MUL]]
1775 %sub = sub i32 16, %a0
1776 %mul = mul i32 %sub, -4
1780 define <2 x i32> @mulsub2_vec(<2 x i32> %a0) {
1781 ; CHECK-LABEL: @mulsub2_vec(
1782 ; CHECK-NEXT: [[SUB_NEG:%.*]] = shl <2 x i32> [[A0:%.*]], splat (i32 2)
1783 ; CHECK-NEXT: [[MUL:%.*]] = add <2 x i32> [[SUB_NEG]], splat (i32 -64)
1784 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1786 %sub = sub <2 x i32> <i32 16, i32 16>, %a0
1787 %mul = mul <2 x i32> %sub, <i32 -4, i32 -4>
1791 define <2 x i32> @mulsub2_vec_nonuniform(<2 x i32> %a0) {
1792 ; CHECK-LABEL: @mulsub2_vec_nonuniform(
1793 ; CHECK-NEXT: [[SUB_NEG:%.*]] = add <2 x i32> [[A0:%.*]], <i32 -16, i32 -32>
1794 ; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], <i32 2, i32 3>
1795 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1797 %sub = sub <2 x i32> <i32 16, i32 32>, %a0
1798 %mul = mul <2 x i32> %sub, <i32 -4, i32 -8>
1802 define <2 x i32> @mulsub2_vec_nonuniform_poison(<2 x i32> %a0) {
1803 ; CHECK-LABEL: @mulsub2_vec_nonuniform_poison(
1804 ; CHECK-NEXT: [[SUB_NEG:%.*]] = add <2 x i32> [[A0:%.*]], <i32 -16, i32 -32>
1805 ; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], <i32 2, i32 0>
1806 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1808 %sub = sub <2 x i32> <i32 16, i32 32>, %a0
1809 %mul = mul <2 x i32> %sub, <i32 -4, i32 poison>
1813 define i8 @mulsub_nsw(i8 %a1, i8 %a2) {
1814 ; CHECK-LABEL: @mulsub_nsw(
1815 ; CHECK-NEXT: [[A_NEG:%.*]] = sub nsw i8 [[A2:%.*]], [[A1:%.*]]
1816 ; CHECK-NEXT: [[MUL:%.*]] = shl nsw i8 [[A_NEG]], 1
1817 ; CHECK-NEXT: ret i8 [[MUL]]
1819 %a = sub nsw i8 %a1, %a2
1820 %mul = mul nsw i8 %a, -2
1824 ; It would be safe to keep the nsw on the shl here, but only because the mul
1825 ; to shl transform happens to replace poison with 0.
1826 define <2 x i8> @mulsub_nsw_poison(<2 x i8> %a1, <2 x i8> %a2) {
1827 ; CHECK-LABEL: @mulsub_nsw_poison(
1828 ; CHECK-NEXT: [[A_NEG:%.*]] = sub nsw <2 x i8> [[A2:%.*]], [[A1:%.*]]
1829 ; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i8> [[A_NEG]], <i8 1, i8 0>
1830 ; CHECK-NEXT: ret <2 x i8> [[MUL]]
1832 %a = sub nsw <2 x i8> %a1, %a2
1833 %mul = mul nsw <2 x i8> %a, <i8 -2, i8 poison>
1837 define i32 @muladd2(i32 %a0) {
1838 ; CHECK-LABEL: @muladd2(
1839 ; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[A0:%.*]], 2
1840 ; CHECK-NEXT: [[MUL:%.*]] = sub i32 -64, [[TMP1]]
1841 ; CHECK-NEXT: ret i32 [[MUL]]
1843 %add = add i32 %a0, 16
1844 %mul = mul i32 %add, -4
1848 define <2 x i32> @muladd2_vec(<2 x i32> %a0) {
1849 ; CHECK-LABEL: @muladd2_vec(
1850 ; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> [[A0:%.*]], splat (i32 2)
1851 ; CHECK-NEXT: [[MUL:%.*]] = sub <2 x i32> splat (i32 -64), [[TMP1]]
1852 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1854 %add = add <2 x i32> %a0, <i32 16, i32 16>
1855 %mul = mul <2 x i32> %add, <i32 -4, i32 -4>
1859 define <2 x i32> @muladd2_vec_nonuniform(<2 x i32> %a0) {
1860 ; CHECK-LABEL: @muladd2_vec_nonuniform(
1861 ; CHECK-NEXT: [[ADD_NEG:%.*]] = sub <2 x i32> <i32 -16, i32 -32>, [[A0:%.*]]
1862 ; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[ADD_NEG]], <i32 2, i32 3>
1863 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1865 %add = add <2 x i32> %a0, <i32 16, i32 32>
1866 %mul = mul <2 x i32> %add, <i32 -4, i32 -8>
1870 define <2 x i32> @muladd2_vec_nonuniform_poison(<2 x i32> %a0) {
1871 ; CHECK-LABEL: @muladd2_vec_nonuniform_poison(
1872 ; CHECK-NEXT: [[ADD_NEG:%.*]] = sub <2 x i32> <i32 -16, i32 -32>, [[A0:%.*]]
1873 ; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[ADD_NEG]], <i32 2, i32 0>
1874 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
1876 %add = add <2 x i32> %a0, <i32 16, i32 32>
1877 %mul = mul <2 x i32> %add, <i32 -4, i32 poison>
1881 define i32 @mulmuladd2(i32 %a0, i32 %a1) {
1882 ; CHECK-LABEL: @mulmuladd2(
1883 ; CHECK-NEXT: [[ADD_NEG:%.*]] = sub i32 1073741808, [[A0:%.*]]
1884 ; CHECK-NEXT: [[MUL1_NEG:%.*]] = mul i32 [[ADD_NEG]], [[A1:%.*]]
1885 ; CHECK-NEXT: [[MUL2:%.*]] = shl i32 [[MUL1_NEG]], 2
1886 ; CHECK-NEXT: ret i32 [[MUL2]]
1888 %add = add i32 %a0, 16
1889 %mul1 = mul i32 %add, %a1
1890 %mul2 = mul i32 %mul1, -4
1893 define i32 @mulmuladd2_extrause0(i32 %a0, i32 %a1) {
1894 ; CHECK-LABEL: @mulmuladd2_extrause0(
1895 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A0:%.*]], 16
1896 ; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[ADD]], [[A1:%.*]]
1897 ; CHECK-NEXT: call void @use32(i32 [[MUL1]])
1898 ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], -4
1899 ; CHECK-NEXT: ret i32 [[MUL2]]
1901 %add = add i32 %a0, 16
1902 %mul1 = mul i32 %add, %a1
1903 call void @use32(i32 %mul1)
1904 %mul2 = mul i32 %mul1, -4
1907 define i32 @mulmuladd2_extrause1(i32 %a0, i32 %a1) {
1908 ; CHECK-LABEL: @mulmuladd2_extrause1(
1909 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A0:%.*]], 16
1910 ; CHECK-NEXT: call void @use32(i32 [[ADD]])
1911 ; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[ADD]], [[A1:%.*]]
1912 ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], -4
1913 ; CHECK-NEXT: ret i32 [[MUL2]]
1915 %add = add i32 %a0, 16
1916 call void @use32(i32 %add)
1917 %mul1 = mul i32 %add, %a1
1918 %mul2 = mul i32 %mul1, -4
1921 define i32 @mulmuladd2_extrause2(i32 %a0, i32 %a1) {
1922 ; CHECK-LABEL: @mulmuladd2_extrause2(
1923 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A0:%.*]], 16
1924 ; CHECK-NEXT: call void @use32(i32 [[ADD]])
1925 ; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[ADD]], [[A1:%.*]]
1926 ; CHECK-NEXT: call void @use32(i32 [[MUL1]])
1927 ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], -4
1928 ; CHECK-NEXT: ret i32 [[MUL2]]
1930 %add = add i32 %a0, 16
1931 call void @use32(i32 %add)
1932 %mul1 = mul i32 %add, %a1
1933 call void @use32(i32 %mul1)
1934 %mul2 = mul i32 %mul1, -4
1938 define i32 @mulnot(i32 %a0) {
1939 ; CHECK-LABEL: @mulnot(
1940 ; CHECK-NEXT: [[ADD_NEG:%.*]] = shl i32 [[A0:%.*]], 2
1941 ; CHECK-NEXT: [[MUL:%.*]] = add i32 [[ADD_NEG]], 4
1942 ; CHECK-NEXT: ret i32 [[MUL]]
1944 %add = xor i32 %a0, -1
1945 %mul = mul i32 %add, -4
1949 define i32 @mulnot_extrause(i32 %a0) {
1950 ; CHECK-LABEL: @mulnot_extrause(
1951 ; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A0:%.*]], -1
1952 ; CHECK-NEXT: call void @use32(i32 [[NOT]])
1953 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[NOT]], -4
1954 ; CHECK-NEXT: ret i32 [[MUL]]
1956 %not = xor i32 %a0, -1
1957 call void @use32(i32 %not)
1958 %mul = mul i32 %not, -4
1962 define i32 @zext_negpow2(i8 %x) {
1963 ; CHECK-LABEL: @zext_negpow2(
1964 ; CHECK-NEXT: [[X_NEG:%.*]] = sub i8 0, [[X:%.*]]
1965 ; CHECK-NEXT: [[X_NEG_Z:%.*]] = zext i8 [[X_NEG]] to i32
1966 ; CHECK-NEXT: [[R:%.*]] = shl nuw i32 [[X_NEG_Z]], 24
1967 ; CHECK-NEXT: ret i32 [[R]]
1969 %zx = zext i8 %x to i32
1970 %r = mul i32 %zx, -16777216 ; -1 << 24
1976 define <2 x i14> @zext_negpow2_vec(<2 x i5> %x) {
1977 ; CHECK-LABEL: @zext_negpow2_vec(
1978 ; CHECK-NEXT: [[X_NEG:%.*]] = sub <2 x i5> zeroinitializer, [[X:%.*]]
1979 ; CHECK-NEXT: [[X_NEG_Z:%.*]] = zext <2 x i5> [[X_NEG]] to <2 x i14>
1980 ; CHECK-NEXT: [[R:%.*]] = shl <2 x i14> [[X_NEG_Z]], splat (i14 11)
1981 ; CHECK-NEXT: ret <2 x i14> [[R]]
1983 %zx = zext <2 x i5> %x to <2 x i14>
1984 %r = mul <2 x i14> %zx, <i14 -2048, i14 -2048> ; -1 << 11
1988 ; negative test - mul must be big enough to cover bitwidth diff
1990 define i32 @zext_negpow2_too_small(i8 %x) {
1991 ; CHECK-LABEL: @zext_negpow2_too_small(
1992 ; CHECK-NEXT: [[ZX:%.*]] = zext i8 [[X:%.*]] to i32
1993 ; CHECK-NEXT: [[R:%.*]] = mul nsw i32 [[ZX]], -8388608
1994 ; CHECK-NEXT: ret i32 [[R]]
1996 %zx = zext i8 %x to i32
1997 %r = mul i32 %zx, -8388608 ; -1 << 23
2001 define i16 @sext_negpow2(i9 %x) {
2002 ; CHECK-LABEL: @sext_negpow2(
2003 ; CHECK-NEXT: [[X_NEG:%.*]] = sub i9 0, [[X:%.*]]
2004 ; CHECK-NEXT: [[X_NEG_Z:%.*]] = zext i9 [[X_NEG]] to i16
2005 ; CHECK-NEXT: [[R:%.*]] = shl i16 [[X_NEG_Z]], 10
2006 ; CHECK-NEXT: ret i16 [[R]]
2008 %sx = sext i9 %x to i16
2009 %r = mul i16 %sx, -1024 ; -1 << 10
2013 ; splat constant with poison element(s)
2015 define <2 x i16> @sext_negpow2_vec(<2 x i8> %x) {
2016 ; CHECK-LABEL: @sext_negpow2_vec(
2017 ; CHECK-NEXT: [[X_NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X:%.*]]
2018 ; CHECK-NEXT: [[X_NEG_Z:%.*]] = zext <2 x i8> [[X_NEG]] to <2 x i16>
2019 ; CHECK-NEXT: [[R:%.*]] = shl nuw <2 x i16> [[X_NEG_Z]], splat (i16 8)
2020 ; CHECK-NEXT: ret <2 x i16> [[R]]
2022 %sx = sext <2 x i8> %x to <2 x i16>
2023 %r = mul <2 x i16> %sx, <i16 -256, i16 poison> ; -1 << 8
2027 ; negative test - mul must be big enough to cover bitwidth diff
2029 define <2 x i16> @sext_negpow2_too_small_vec(<2 x i8> %x) {
2030 ; CHECK-LABEL: @sext_negpow2_too_small_vec(
2031 ; CHECK-NEXT: [[SX:%.*]] = sext <2 x i8> [[X:%.*]] to <2 x i16>
2032 ; CHECK-NEXT: [[R:%.*]] = mul nsw <2 x i16> [[SX]], <i16 -128, i16 poison>
2033 ; CHECK-NEXT: ret <2 x i16> [[R]]
2035 %sx = sext <2 x i8> %x to <2 x i16>
2036 %r = mul <2 x i16> %sx, <i16 -128, i16 poison> ; -1 << 7
2040 ; negative test - too many uses
2042 define i32 @zext_negpow2_use(i8 %x) {
2043 ; CHECK-LABEL: @zext_negpow2_use(
2044 ; CHECK-NEXT: [[ZX:%.*]] = zext i8 [[X:%.*]] to i32
2045 ; CHECK-NEXT: call void @use32(i32 [[ZX]])
2046 ; CHECK-NEXT: [[R:%.*]] = mul i32 [[ZX]], -16777216
2047 ; CHECK-NEXT: ret i32 [[R]]
2049 %zx = zext i8 %x to i32
2050 call void @use32(i32 %zx)
2051 %r = mul i32 %zx, -16777216 ; -1 << 24
2055 define i32 @mul_sext_icmp_with_zero(i32 %x) {
2056 ; CHECK-LABEL: @mul_sext_icmp_with_zero(
2057 ; CHECK-NEXT: ret i32 0
2059 %cmp = icmp eq i32 %x, 0
2060 %sext = sext i1 %cmp to i32
2061 %mul = mul i32 %sext, %x
2065 define i32 @test_mul_sext_bool(i1 %x, i32 %y) {
2066 ; CHECK-LABEL: @test_mul_sext_bool(
2067 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[Y:%.*]]
2068 ; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[TMP1]], i32 0
2069 ; CHECK-NEXT: ret i32 [[MUL]]
2071 %sext = sext i1 %x to i32
2072 %mul = mul i32 %sext, %y
2076 define i32 @test_mul_sext_bool_nuw(i1 %x, i32 %y) {
2077 ; CHECK-LABEL: @test_mul_sext_bool_nuw(
2078 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[Y:%.*]]
2079 ; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[TMP1]], i32 0
2080 ; CHECK-NEXT: ret i32 [[MUL]]
2082 %sext = sext i1 %x to i32
2083 %mul = mul nuw i32 %sext, %y
2087 define i32 @test_mul_sext_bool_nsw(i1 %x, i32 %y) {
2088 ; CHECK-LABEL: @test_mul_sext_bool_nsw(
2089 ; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i32 0, [[Y:%.*]]
2090 ; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[TMP1]], i32 0
2091 ; CHECK-NEXT: ret i32 [[MUL]]
2093 %sext = sext i1 %x to i32
2094 %mul = mul nsw i32 %sext, %y
2098 define i32 @test_mul_sext_bool_nuw_nsw(i1 %x, i32 %y) {
2099 ; CHECK-LABEL: @test_mul_sext_bool_nuw_nsw(
2100 ; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i32 0, [[Y:%.*]]
2101 ; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[TMP1]], i32 0
2102 ; CHECK-NEXT: ret i32 [[MUL]]
2104 %sext = sext i1 %x to i32
2105 %mul = mul nuw nsw i32 %sext, %y
2109 define i32 @test_mul_sext_bool_commuted(i1 %x, i32 %y) {
2110 ; CHECK-LABEL: @test_mul_sext_bool_commuted(
2111 ; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[Y:%.*]], -2
2112 ; CHECK-NEXT: [[YY_NEG:%.*]] = add i32 [[TMP1]], 1
2113 ; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[YY_NEG]], i32 0
2114 ; CHECK-NEXT: ret i32 [[MUL]]
2117 %sext = sext i1 %x to i32
2118 %mul = mul i32 %yy, %sext
2122 define i32 @test_mul_sext_nonbool(i2 %x, i32 %y) {
2123 ; CHECK-LABEL: @test_mul_sext_nonbool(
2124 ; CHECK-NEXT: [[SEXT:%.*]] = sext i2 [[X:%.*]] to i32
2125 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[Y:%.*]], [[SEXT]]
2126 ; CHECK-NEXT: ret i32 [[MUL]]
2128 %sext = sext i2 %x to i32
2129 %mul = mul i32 %sext, %y
2133 define i32 @test_mul_sext_multiuse(i1 %x, i32 %y) {
2134 ; CHECK-LABEL: @test_mul_sext_multiuse(
2135 ; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[X:%.*]] to i32
2136 ; CHECK-NEXT: tail call void @use(i32 [[SEXT]])
2137 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[Y:%.*]], [[SEXT]]
2138 ; CHECK-NEXT: ret i32 [[MUL]]
2140 %sext = sext i1 %x to i32
2141 tail call void @use(i32 %sext)
2142 %mul = mul i32 %sext, %y
2146 define i8 @mul_nsw_nonneg(i8 %x, i8 %y) {
2147 ; CHECK-LABEL: @mul_nsw_nonneg(
2148 ; CHECK-NEXT: [[X_NNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
2149 ; CHECK-NEXT: call void @llvm.assume(i1 [[X_NNEG]])
2150 ; CHECK-NEXT: [[Y_NNEG:%.*]] = icmp sgt i8 [[Y:%.*]], -1
2151 ; CHECK-NEXT: call void @llvm.assume(i1 [[Y_NNEG]])
2152 ; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i8 [[X]], [[Y]]
2153 ; CHECK-NEXT: ret i8 [[MUL]]
2155 %x.nneg = icmp sge i8 %x, 0
2156 call void @llvm.assume(i1 %x.nneg)
2157 %y.nneg = icmp sge i8 %y, 0
2158 call void @llvm.assume(i1 %y.nneg)
2159 %mul = mul nsw i8 %x, %y
2163 define i8 @mul_nsw_not_nonneg1(i8 %x, i8 %y) {
2164 ; CHECK-LABEL: @mul_nsw_not_nonneg1(
2165 ; CHECK-NEXT: [[Y_NNEG:%.*]] = icmp sgt i8 [[Y:%.*]], -1
2166 ; CHECK-NEXT: call void @llvm.assume(i1 [[Y_NNEG]])
2167 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[X:%.*]], [[Y]]
2168 ; CHECK-NEXT: ret i8 [[MUL]]
2170 %y.nneg = icmp sge i8 %y, 0
2171 call void @llvm.assume(i1 %y.nneg)
2172 %mul = mul nsw i8 %x, %y
2176 define i8 @mul_nsw_not_nonneg2(i8 %x, i8 %y) {
2177 ; CHECK-LABEL: @mul_nsw_not_nonneg2(
2178 ; CHECK-NEXT: [[X_NNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
2179 ; CHECK-NEXT: call void @llvm.assume(i1 [[X_NNEG]])
2180 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[X]], [[Y:%.*]]
2181 ; CHECK-NEXT: ret i8 [[MUL]]
2183 %x.nneg = icmp sge i8 %x, 0
2184 call void @llvm.assume(i1 %x.nneg)
2185 %mul = mul nsw i8 %x, %y
2189 define i8 @mul_not_nsw_nonneg(i8 %x, i8 %y) {
2190 ; CHECK-LABEL: @mul_not_nsw_nonneg(
2191 ; CHECK-NEXT: [[X_NNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
2192 ; CHECK-NEXT: call void @llvm.assume(i1 [[X_NNEG]])
2193 ; CHECK-NEXT: [[Y_NNEG:%.*]] = icmp sgt i8 [[Y:%.*]], -1
2194 ; CHECK-NEXT: call void @llvm.assume(i1 [[Y_NNEG]])
2195 ; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[X]], [[Y]]
2196 ; CHECK-NEXT: ret i8 [[MUL]]
2198 %x.nneg = icmp sge i8 %x, 0
2199 call void @llvm.assume(i1 %x.nneg)
2200 %y.nneg = icmp sge i8 %y, 0
2201 call void @llvm.assume(i1 %y.nneg)
2202 %mul = mul i8 %x, %y