@@ -491,5 +491,140 @@ define i64 @test12(i32 %V) {
491
491
ret i64 %add
492
492
}
493
493
494
+ define i64 @test13 (i32 %V ) {
495
+ ; CHECK-LABEL: @test13(
496
+ ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !2
497
+ ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range !3
498
+ ; CHECK-NEXT: [[SUBCONV:%.*]] = sub nsw i32 [[CALL1]], [[CALL2]]
499
+ ; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[SUBCONV]] to i64
500
+ ; CHECK-NEXT: ret i64 [[SUB]]
501
+ ;
502
+ %call1 = call i32 @callee (), !range !2
503
+ %call2 = call i32 @callee (), !range !3
504
+ %sext1 = sext i32 %call1 to i64
505
+ %sext2 = sext i32 %call2 to i64
506
+ %sub = sub i64 %sext1 , %sext2
507
+ ret i64 %sub
508
+ }
509
+
510
+ define i64 @test14 (i32 %V ) {
511
+ ; CHECK-LABEL: @test14(
512
+ ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !2
513
+ ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range !0
514
+ ; CHECK-NEXT: [[SUBCONV:%.*]] = sub nuw nsw i32 [[CALL1]], [[CALL2]]
515
+ ; CHECK-NEXT: [[SUB:%.*]] = zext i32 [[SUBCONV]] to i64
516
+ ; CHECK-NEXT: ret i64 [[SUB]]
517
+ ;
518
+ %call1 = call i32 @callee (), !range !2
519
+ %call2 = call i32 @callee (), !range !0
520
+ %zext1 = zext i32 %call1 to i64
521
+ %zext2 = zext i32 %call2 to i64
522
+ %sub = sub i64 %zext1 , %zext2
523
+ ret i64 %sub
524
+ }
525
+
526
+ define i64 @test15 (i32 %V ) {
527
+ ; CHECK-LABEL: @test15(
528
+ ; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 1
529
+ ; CHECK-NEXT: [[SUBCONV:%.*]] = sub nsw i32 8, [[ASHR]]
530
+ ; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[SUBCONV]] to i64
531
+ ; CHECK-NEXT: ret i64 [[SUB]]
532
+ ;
533
+ %ashr = ashr i32 %V , 1
534
+ %sext = sext i32 %ashr to i64
535
+ %sub = sub i64 8 , %sext
536
+ ret i64 %sub
537
+ }
538
+
539
+ define <2 x i64 > @test15vec (<2 x i32 > %V ) {
540
+ ; CHECK-LABEL: @test15vec(
541
+ ; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], <i32 1, i32 1>
542
+ ; CHECK-NEXT: [[SUBCONV:%.*]] = sub nsw <2 x i32> <i32 8, i32 8>, [[ASHR]]
543
+ ; CHECK-NEXT: [[SUB:%.*]] = sext <2 x i32> [[SUBCONV]] to <2 x i64>
544
+ ; CHECK-NEXT: ret <2 x i64> [[SUB]]
545
+ ;
546
+ %ashr = ashr <2 x i32 > %V , <i32 1 , i32 1 >
547
+ %sext = sext <2 x i32 > %ashr to <2 x i64 >
548
+ %sub = sub <2 x i64 > <i64 8 , i64 8 >, %sext
549
+ ret <2 x i64 > %sub
550
+ }
551
+
552
+ define i64 @test16 (i32 %V ) {
553
+ ; CHECK-LABEL: @test16(
554
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[V:%.*]], 1
555
+ ; CHECK-NEXT: [[SUBCONV:%.*]] = sub nuw i32 -2, [[LSHR]]
556
+ ; CHECK-NEXT: [[SUB:%.*]] = zext i32 [[SUBCONV]] to i64
557
+ ; CHECK-NEXT: ret i64 [[SUB]]
558
+ ;
559
+ %lshr = lshr i32 %V , 1
560
+ %zext = zext i32 %lshr to i64
561
+ %sub = sub i64 4294967294 , %zext
562
+ ret i64 %sub
563
+ }
564
+
565
+ define <2 x i64 > @test16vec (<2 x i32 > %V ) {
566
+ ; CHECK-LABEL: @test16vec(
567
+ ; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> [[V:%.*]], <i32 1, i32 1>
568
+ ; CHECK-NEXT: [[SUBCONV:%.*]] = sub nuw <2 x i32> <i32 -2, i32 -2>, [[LSHR]]
569
+ ; CHECK-NEXT: [[SUB:%.*]] = zext <2 x i32> [[SUBCONV]] to <2 x i64>
570
+ ; CHECK-NEXT: ret <2 x i64> [[SUB]]
571
+ ;
572
+ %lshr = lshr <2 x i32 > %V , <i32 1 , i32 1 >
573
+ %zext = zext <2 x i32 > %lshr to <2 x i64 >
574
+ %sub = sub <2 x i64 > <i64 4294967294 , i64 4294967294 >, %zext
575
+ ret <2 x i64 > %sub
576
+ }
577
+
578
+ ; Negative test. Both have the same range so we can't guarantee the subtract
579
+ ; won't wrap.
580
+ define i64 @test17 (i32 %V ) {
581
+ ; CHECK-LABEL: @test17(
582
+ ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !0
583
+ ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range !0
584
+ ; CHECK-NEXT: [[SEXT1:%.*]] = zext i32 [[CALL1]] to i64
585
+ ; CHECK-NEXT: [[SEXT2:%.*]] = zext i32 [[CALL2]] to i64
586
+ ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[SEXT1]], [[SEXT2]]
587
+ ; CHECK-NEXT: ret i64 [[SUB]]
588
+ ;
589
+ %call1 = call i32 @callee (), !range !0
590
+ %call2 = call i32 @callee (), !range !0
591
+ %sext1 = zext i32 %call1 to i64
592
+ %sext2 = zext i32 %call2 to i64
593
+ %sub = sub i64 %sext1 , %sext2
594
+ ret i64 %sub
595
+ }
596
+
597
+ ; Negative test. LHS is large positive 32-bit number. Range of callee can
598
+ ; cause overflow.
599
+ define i64 @test18 (i32 %V ) {
600
+ ; CHECK-LABEL: @test18(
601
+ ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !1
602
+ ; CHECK-NEXT: [[SEXT1:%.*]] = sext i32 [[CALL1]] to i64
603
+ ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 2147481648, [[SEXT1]]
604
+ ; CHECK-NEXT: ret i64 [[SUB]]
605
+ ;
606
+ %call1 = call i32 @callee (), !range !1
607
+ %sext1 = sext i32 %call1 to i64
608
+ %sub = sub i64 2147481648 , %sext1
609
+ ret i64 %sub
610
+ }
611
+
612
+ ; Negative test. LHS is large negative 32-bit number. Range of callee can
613
+ ; cause overflow.
614
+ define i64 @test19 (i32 %V ) {
615
+ ; CHECK-LABEL: @test19(
616
+ ; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range !0
617
+ ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[CALL1]] to i64
618
+ ; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i64 -2147481648, [[TMP1]]
619
+ ; CHECK-NEXT: ret i64 [[SUB]]
620
+ ;
621
+ %call1 = call i32 @callee (), !range !0
622
+ %sext1 = sext i32 %call1 to i64
623
+ %sub = sub i64 -2147481648 , %sext1
624
+ ret i64 %sub
625
+ }
626
+
494
627
!0 = !{ i32 0 , i32 2000 }
495
628
!1 = !{ i32 -2000 , i32 0 }
629
+ !2 = !{ i32 -512 , i32 -255 }
630
+ !3 = !{ i32 -128 , i32 0 }
0 commit comments