@@ -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,167 @@ 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
+
414
+ define i32 @shl_sub_lshr (i32 %x , i32 %c , i32 %y ) {
415
+ ; CHECK-LABEL: @shl_sub_lshr(
416
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
417
+ ; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[SHL]], [[Y:%.*]]
418
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[SUB]], [[C]]
419
+ ; CHECK-NEXT: ret i32 [[LSHR]]
420
+ ;
421
+ %shl = shl nuw i32 %x , %c
422
+ %sub = sub nuw i32 %shl , %y
423
+ %lshr = lshr i32 %sub , %c
424
+ ret i32 %lshr
425
+ }
426
+
427
+ define i32 @shl_or_lshr (i32 %x , i32 %c , i32 %y ) {
428
+ ; CHECK-LABEL: @shl_or_lshr(
429
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
430
+ ; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[Y:%.*]]
431
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[OR]], [[C]]
432
+ ; CHECK-NEXT: ret i32 [[LSHR]]
433
+ ;
434
+ %shl = shl nuw i32 %x , %c
435
+ %or = or i32 %shl , %y
436
+ %lshr = lshr i32 %or , %c
437
+ ret i32 %lshr
438
+ }
439
+
440
+ define i32 @shl_or_disjoint_lshr (i32 %x , i32 %c , i32 %y ) {
441
+ ; CHECK-LABEL: @shl_or_disjoint_lshr(
442
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
443
+ ; CHECK-NEXT: [[OR:%.*]] = or disjoint i32 [[SHL]], [[Y:%.*]]
444
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[OR]], [[C]]
445
+ ; CHECK-NEXT: ret i32 [[LSHR]]
446
+ ;
447
+ %shl = shl nuw i32 %x , %c
448
+ %or = or disjoint i32 %shl , %y
449
+ %lshr = lshr i32 %or , %c
450
+ ret i32 %lshr
451
+ }
452
+
453
+ define i32 @shl_or_lshr_comm (i32 %x , i32 %c , i32 %y ) {
454
+ ; CHECK-LABEL: @shl_or_lshr_comm(
455
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
456
+ ; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[Y:%.*]]
457
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[OR]], [[C]]
458
+ ; CHECK-NEXT: ret i32 [[LSHR]]
459
+ ;
460
+ %shl = shl nuw i32 %x , %c
461
+ %or = or i32 %y , %shl
462
+ %lshr = lshr i32 %or , %c
463
+ ret i32 %lshr
464
+ }
465
+
466
+ define i32 @shl_or_disjoint_lshr_comm (i32 %x , i32 %c , i32 %y ) {
467
+ ; CHECK-LABEL: @shl_or_disjoint_lshr_comm(
468
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
469
+ ; CHECK-NEXT: [[OR:%.*]] = or disjoint i32 [[SHL]], [[Y:%.*]]
470
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[OR]], [[C]]
471
+ ; CHECK-NEXT: ret i32 [[LSHR]]
472
+ ;
473
+ %shl = shl nuw i32 %x , %c
474
+ %or = or disjoint i32 %y , %shl
475
+ %lshr = lshr i32 %or , %c
476
+ ret i32 %lshr
477
+ }
478
+
479
+ define i32 @shl_xor_lshr (i32 %x , i32 %c , i32 %y ) {
480
+ ; CHECK-LABEL: @shl_xor_lshr(
481
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
482
+ ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[SHL]], [[Y:%.*]]
483
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[XOR]], [[C]]
484
+ ; CHECK-NEXT: ret i32 [[LSHR]]
485
+ ;
486
+ %shl = shl nuw i32 %x , %c
487
+ %xor = xor i32 %shl , %y
488
+ %lshr = lshr i32 %xor , %c
489
+ ret i32 %lshr
490
+ }
491
+
492
+
493
+ define i32 @shl_xor_lshr_comm (i32 %x , i32 %c , i32 %y ) {
494
+ ; CHECK-LABEL: @shl_xor_lshr_comm(
495
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
496
+ ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[SHL]], [[Y:%.*]]
497
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[XOR]], [[C]]
498
+ ; CHECK-NEXT: ret i32 [[LSHR]]
499
+ ;
500
+ %shl = shl nuw i32 %x , %c
501
+ %xor = xor i32 %y , %shl
502
+ %lshr = lshr i32 %xor , %c
503
+ ret i32 %lshr
504
+ }
505
+
506
+ ; Negative test
507
+
508
+ define i32 @shl_and_lshr (i32 %x , i32 %c , i32 %y ) {
509
+ ; CHECK-LABEL: @shl_and_lshr(
510
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
511
+ ; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], [[Y:%.*]]
512
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[AND]], [[C]]
513
+ ; CHECK-NEXT: ret i32 [[LSHR]]
514
+ ;
515
+ %shl = shl nuw i32 %x , %c
516
+ %and = and i32 %shl , %y
517
+ %lshr = lshr i32 %and , %c
518
+ ret i32 %lshr
519
+ }
520
+
363
521
; Negative test
364
522
523
+ define i32 @shl_add_lshr_neg (i32 %x , i32 %y , i32 %z ) {
524
+ ; CHECK-LABEL: @shl_add_lshr_neg(
525
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[Y:%.*]]
526
+ ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[Z:%.*]]
527
+ ; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[ADD]], [[Z]]
528
+ ; CHECK-NEXT: ret i32 [[RES]]
529
+ ;
530
+ %shl = shl nuw i32 %x , %y
531
+ %add = add nuw nsw i32 %shl , %z
532
+ %res = lshr exact i32 %add , %z
533
+ ret i32 %res
534
+ }
535
+
365
536
define i32 @mul_splat_fold_wrong_mul_const (i32 %x ) {
366
537
; CHECK-LABEL: @mul_splat_fold_wrong_mul_const(
367
538
; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65538
@@ -375,6 +546,21 @@ define i32 @mul_splat_fold_wrong_mul_const(i32 %x) {
375
546
376
547
; Negative test
377
548
549
+ define i32 @shl_add_lshr_multiuse (i32 %x , i32 %y , i32 %z ) {
550
+ ; CHECK-LABEL: @shl_add_lshr_multiuse(
551
+ ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[Y:%.*]]
552
+ ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[Z:%.*]]
553
+ ; CHECK-NEXT: call void @use(i32 [[ADD]])
554
+ ; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[ADD]], [[Z]]
555
+ ; CHECK-NEXT: ret i32 [[RES]]
556
+ ;
557
+ %shl = shl nuw i32 %x , %y
558
+ %add = add nuw nsw i32 %shl , %z
559
+ call void @use (i32 %add )
560
+ %res = lshr exact i32 %add , %z
561
+ ret i32 %res
562
+ }
563
+
378
564
define i32 @mul_splat_fold_wrong_lshr_const (i32 %x ) {
379
565
; CHECK-LABEL: @mul_splat_fold_wrong_lshr_const(
380
566
; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65537
0 commit comments