@@ -163,6 +163,18 @@ define <2 x i8> @lshr_exact_splat_vec(<2 x i8> %x) {
163
163
ret <2 x i8 > %lshr
164
164
}
165
165
166
+ define <2 x i8 > @lshr_exact_splat_vec_nuw (<2 x i8 > %x ) {
167
+ ; CHECK-LABEL: @lshr_exact_splat_vec_nuw(
168
+ ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 1, i8 1>
169
+ ; CHECK-NEXT: [[LSHR:%.*]] = and <2 x i8> [[TMP1]], <i8 63, i8 63>
170
+ ; CHECK-NEXT: ret <2 x i8> [[LSHR]]
171
+ ;
172
+ %shl = shl nuw <2 x i8 > %x , <i8 2 , i8 2 >
173
+ %add = add nuw <2 x i8 > %shl , <i8 4 , i8 4 >
174
+ %lshr = lshr <2 x i8 > %add , <i8 2 , i8 2 >
175
+ ret <2 x i8 > %lshr
176
+ }
177
+
166
178
define i8 @shl_add (i8 %x , i8 %y ) {
167
179
; CHECK-LABEL: @shl_add(
168
180
; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[Y:%.*]], 2
@@ -360,8 +372,197 @@ define <3 x i14> @mul_splat_fold_vec(<3 x i14> %x) {
360
372
ret <3 x i14 > %t
361
373
}
362
374
375
+ define i32 @shl_add_lshr_flag_preservation (i32 %x , i32 %c , i32 %y ) {
376
+ ; CHECK-LABEL: @shl_add_lshr_flag_preservation(
377
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
378
+ ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[Y:%.*]]
379
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[ADD]], [[C]]
380
+ ; CHECK-NEXT: ret i32 [[LSHR]]
381
+ ;
382
+ %shl = shl nuw i32 %x , %c
383
+ %add = add nuw nsw i32 %shl , %y
384
+ %lshr = lshr exact i32 %add , %c
385
+ ret i32 %lshr
386
+ }
387
+
388
+ define i32 @shl_add_lshr (i32 %x , i32 %c , i32 %y ) {
389
+ ; CHECK-LABEL: @shl_add_lshr(
390
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
391
+ ; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[SHL]], [[Y:%.*]]
392
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[ADD]], [[C]]
393
+ ; CHECK-NEXT: ret i32 [[LSHR]]
394
+ ;
395
+ %shl = shl nuw i32 %x , %c
396
+ %add = add nuw i32 %shl , %y
397
+ %lshr = lshr i32 %add , %c
398
+ ret i32 %lshr
399
+ }
400
+
401
+ define i32 @shl_add_lshr_comm (i32 %x , i32 %c , i32 %y ) {
402
+ ; CHECK-LABEL: @shl_add_lshr_comm(
403
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
404
+ ; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[SHL]], [[Y:%.*]]
405
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[ADD]], [[C]]
406
+ ; CHECK-NEXT: ret i32 [[LSHR]]
407
+ ;
408
+ %shl = shl nuw i32 %x , %c
409
+ %add = add nuw i32 %y , %shl
410
+ %lshr = lshr i32 %add , %c
411
+ ret i32 %lshr
412
+ }
413
+
363
414
; Negative test
364
415
416
+ define i32 @shl_sub_lshr_not_exact (i32 %x , i32 %c , i32 %y ) {
417
+ ; CHECK-LABEL: @shl_sub_lshr_not_exact(
418
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
419
+ ; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[SHL]], [[Y:%.*]]
420
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[SUB]], [[C]]
421
+ ; CHECK-NEXT: ret i32 [[LSHR]]
422
+ ;
423
+ %shl = shl nuw i32 %x , %c
424
+ %sub = sub nuw i32 %shl , %y
425
+ %lshr = lshr i32 %sub , %c
426
+ ret i32 %lshr
427
+ }
428
+
429
+ ; Negative test
430
+
431
+ define i32 @shl_sub_lshr_no_nuw (i32 %x , i32 %c , i32 %y ) {
432
+ ; CHECK-LABEL: @shl_sub_lshr_no_nuw(
433
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[X:%.*]], [[C:%.*]]
434
+ ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[SHL]], [[Y:%.*]]
435
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]
436
+ ; CHECK-NEXT: ret i32 [[LSHR]]
437
+ ;
438
+ %shl = shl nsw i32 %x , %c
439
+ %sub = sub nsw i32 %shl , %y
440
+ %lshr = lshr exact i32 %sub , %c
441
+ ret i32 %lshr
442
+ }
443
+
444
+ define i32 @shl_sub_lshr (i32 %x , i32 %c , i32 %y ) {
445
+ ; CHECK-LABEL: @shl_sub_lshr(
446
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
447
+ ; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[SHL]], [[Y:%.*]]
448
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]
449
+ ; CHECK-NEXT: ret i32 [[LSHR]]
450
+ ;
451
+ %shl = shl nuw i32 %x , %c
452
+ %sub = sub nuw nsw i32 %shl , %y
453
+ %lshr = lshr exact i32 %sub , %c
454
+ ret i32 %lshr
455
+ }
456
+
457
+ define i32 @shl_or_lshr (i32 %x , i32 %c , i32 %y ) {
458
+ ; CHECK-LABEL: @shl_or_lshr(
459
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
460
+ ; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[Y:%.*]]
461
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[OR]], [[C]]
462
+ ; CHECK-NEXT: ret i32 [[LSHR]]
463
+ ;
464
+ %shl = shl nuw i32 %x , %c
465
+ %or = or i32 %shl , %y
466
+ %lshr = lshr i32 %or , %c
467
+ ret i32 %lshr
468
+ }
469
+
470
+ define i32 @shl_or_disjoint_lshr (i32 %x , i32 %c , i32 %y ) {
471
+ ; CHECK-LABEL: @shl_or_disjoint_lshr(
472
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
473
+ ; CHECK-NEXT: [[OR:%.*]] = or disjoint i32 [[SHL]], [[Y:%.*]]
474
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[OR]], [[C]]
475
+ ; CHECK-NEXT: ret i32 [[LSHR]]
476
+ ;
477
+ %shl = shl nuw i32 %x , %c
478
+ %or = or disjoint i32 %shl , %y
479
+ %lshr = lshr i32 %or , %c
480
+ ret i32 %lshr
481
+ }
482
+
483
+ define i32 @shl_or_lshr_comm (i32 %x , i32 %c , i32 %y ) {
484
+ ; CHECK-LABEL: @shl_or_lshr_comm(
485
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
486
+ ; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[Y:%.*]]
487
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[OR]], [[C]]
488
+ ; CHECK-NEXT: ret i32 [[LSHR]]
489
+ ;
490
+ %shl = shl nuw i32 %x , %c
491
+ %or = or i32 %y , %shl
492
+ %lshr = lshr i32 %or , %c
493
+ ret i32 %lshr
494
+ }
495
+
496
+ define i32 @shl_or_disjoint_lshr_comm (i32 %x , i32 %c , i32 %y ) {
497
+ ; CHECK-LABEL: @shl_or_disjoint_lshr_comm(
498
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
499
+ ; CHECK-NEXT: [[OR:%.*]] = or disjoint i32 [[SHL]], [[Y:%.*]]
500
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[OR]], [[C]]
501
+ ; CHECK-NEXT: ret i32 [[LSHR]]
502
+ ;
503
+ %shl = shl nuw i32 %x , %c
504
+ %or = or disjoint i32 %y , %shl
505
+ %lshr = lshr i32 %or , %c
506
+ ret i32 %lshr
507
+ }
508
+
509
+ define i32 @shl_xor_lshr (i32 %x , i32 %c , i32 %y ) {
510
+ ; CHECK-LABEL: @shl_xor_lshr(
511
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
512
+ ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[SHL]], [[Y:%.*]]
513
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[XOR]], [[C]]
514
+ ; CHECK-NEXT: ret i32 [[LSHR]]
515
+ ;
516
+ %shl = shl nuw i32 %x , %c
517
+ %xor = xor i32 %shl , %y
518
+ %lshr = lshr i32 %xor , %c
519
+ ret i32 %lshr
520
+ }
521
+
522
+
523
+ define i32 @shl_xor_lshr_comm (i32 %x , i32 %c , i32 %y ) {
524
+ ; CHECK-LABEL: @shl_xor_lshr_comm(
525
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
526
+ ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[SHL]], [[Y:%.*]]
527
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[XOR]], [[C]]
528
+ ; CHECK-NEXT: ret i32 [[LSHR]]
529
+ ;
530
+ %shl = shl nuw i32 %x , %c
531
+ %xor = xor i32 %y , %shl
532
+ %lshr = lshr i32 %xor , %c
533
+ ret i32 %lshr
534
+ }
535
+
536
+ ; Negative test
537
+
538
+ define i32 @shl_and_lshr (i32 %x , i32 %c , i32 %y ) {
539
+ ; CHECK-LABEL: @shl_and_lshr(
540
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
541
+ ; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], [[Y:%.*]]
542
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[AND]], [[C]]
543
+ ; CHECK-NEXT: ret i32 [[LSHR]]
544
+ ;
545
+ %shl = shl nuw i32 %x , %c
546
+ %and = and i32 %shl , %y
547
+ %lshr = lshr i32 %and , %c
548
+ ret i32 %lshr
549
+ }
550
+
551
+ ; Negative test
552
+
553
+ define i32 @shl_add_lshr_neg (i32 %x , i32 %y , i32 %z ) {
554
+ ; CHECK-LABEL: @shl_add_lshr_neg(
555
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[Y:%.*]]
556
+ ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[Z:%.*]]
557
+ ; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[ADD]], [[Z]]
558
+ ; CHECK-NEXT: ret i32 [[RES]]
559
+ ;
560
+ %shl = shl nuw i32 %x , %y
561
+ %add = add nuw nsw i32 %shl , %z
562
+ %res = lshr exact i32 %add , %z
563
+ ret i32 %res
564
+ }
565
+
365
566
define i32 @mul_splat_fold_wrong_mul_const (i32 %x ) {
366
567
; CHECK-LABEL: @mul_splat_fold_wrong_mul_const(
367
568
; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65538
@@ -375,6 +576,21 @@ define i32 @mul_splat_fold_wrong_mul_const(i32 %x) {
375
576
376
577
; Negative test
377
578
579
+ define i32 @shl_add_lshr_multiuse (i32 %x , i32 %y , i32 %z ) {
580
+ ; CHECK-LABEL: @shl_add_lshr_multiuse(
581
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[Y:%.*]]
582
+ ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[Z:%.*]]
583
+ ; CHECK-NEXT: call void @use(i32 [[ADD]])
584
+ ; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[ADD]], [[Z]]
585
+ ; CHECK-NEXT: ret i32 [[RES]]
586
+ ;
587
+ %shl = shl nuw i32 %x , %y
588
+ %add = add nuw nsw i32 %shl , %z
589
+ call void @use (i32 %add )
590
+ %res = lshr exact i32 %add , %z
591
+ ret i32 %res
592
+ }
593
+
378
594
define i32 @mul_splat_fold_wrong_lshr_const (i32 %x ) {
379
595
; CHECK-LABEL: @mul_splat_fold_wrong_lshr_const(
380
596
; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65537
0 commit comments