[llvm] r356489 - [ValueTracking] Use computeConstantRange() for unsigned add/sub overflow

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 19 10:53:56 PDT 2019


Author: nikic
Date: Tue Mar 19 10:53:56 2019
New Revision: 356489

URL: http://llvm.org/viewvc/llvm-project?rev=356489&view=rev
Log:
[ValueTracking] Use computeConstantRange() for unsigned add/sub overflow

Improve computeOverflowForUnsignedAdd/Sub in ValueTracking by
intersecting the computeConstantRange() result into the ConstantRange
created from computeKnownBits(). This allows us to detect some
additional never/always overflows conditions that can't be determined
from known bits.

This revision also adds basic handling for constants to
computeConstantRange(). Non-splat vectors will be handled in a followup.

The signed case will also be handled in a followup, as it needs some
more groundwork.

Differential Revision: https://reviews.llvm.org/D59386

Modified:
    llvm/trunk/lib/Analysis/ValueTracking.cpp
    llvm/trunk/test/Transforms/InstCombine/and2.ll
    llvm/trunk/test/Transforms/InstCombine/saturating-add-sub.ll
    llvm/trunk/test/Transforms/InstCombine/uadd-with-overflow.ll
    llvm/trunk/test/Transforms/LoopVectorize/X86/small-size.ll

Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=356489&r1=356488&r2=356489&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Tue Mar 19 10:53:56 2019
@@ -4077,18 +4077,27 @@ static OverflowResult mapOverflowResult(
   llvm_unreachable("Unknown OverflowResult");
 }
 
+/// Combine constant ranges from computeConstantRange() and computeKnownBits().
+static ConstantRange computeConstantRangeIncludingKnownBits(
+    const Value *V, bool ForSigned, const DataLayout &DL, unsigned Depth,
+    AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT,
+    OptimizationRemarkEmitter *ORE = nullptr, bool UseInstrInfo = true) {
+  KnownBits Known = computeKnownBits(
+      V, DL, Depth, AC, CxtI, DT, ORE, UseInstrInfo);
+  ConstantRange CR = computeConstantRange(V, UseInstrInfo);
+  return ConstantRange::fromKnownBits(Known, ForSigned).intersectWith(CR);
+}
+
 OverflowResult llvm::computeOverflowForUnsignedAdd(
     const Value *LHS, const Value *RHS, const DataLayout &DL,
     AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT,
     bool UseInstrInfo) {
-  KnownBits LHSKnown = computeKnownBits(LHS, DL, /*Depth=*/0, AC, CxtI, DT,
-                                        nullptr, UseInstrInfo);
-  KnownBits RHSKnown = computeKnownBits(RHS, DL, /*Depth=*/0, AC, CxtI, DT,
-                                        nullptr, UseInstrInfo);
-  ConstantRange LHSRange =
-      ConstantRange::fromKnownBits(LHSKnown, /*signed*/ false);
-  ConstantRange RHSRange =
-      ConstantRange::fromKnownBits(RHSKnown, /*signed*/ false);
+  ConstantRange LHSRange = computeConstantRangeIncludingKnownBits(
+      LHS, /*ForSigned=*/false, DL, /*Depth=*/0, AC, CxtI, DT,
+      nullptr, UseInstrInfo);
+  ConstantRange RHSRange = computeConstantRangeIncludingKnownBits(
+      RHS, /*ForSigned=*/false, DL, /*Depth=*/0, AC, CxtI, DT,
+      nullptr, UseInstrInfo);
   return mapOverflowResult(LHSRange.unsignedAddMayOverflow(RHSRange));
 }
 
@@ -4161,12 +4170,10 @@ OverflowResult llvm::computeOverflowForU
                                                    AssumptionCache *AC,
                                                    const Instruction *CxtI,
                                                    const DominatorTree *DT) {
-  KnownBits LHSKnown = computeKnownBits(LHS, DL, /*Depth=*/0, AC, CxtI, DT);
-  KnownBits RHSKnown = computeKnownBits(RHS, DL, /*Depth=*/0, AC, CxtI, DT);
-  ConstantRange LHSRange =
-      ConstantRange::fromKnownBits(LHSKnown, /*signed*/ false);
-  ConstantRange RHSRange =
-      ConstantRange::fromKnownBits(RHSKnown, /*signed*/ false);
+  ConstantRange LHSRange = computeConstantRangeIncludingKnownBits(
+      LHS, /*ForSigned=*/false, DL, /*Depth=*/0, AC, CxtI, DT);
+  ConstantRange RHSRange = computeConstantRangeIncludingKnownBits(
+      RHS, /*ForSigned=*/false, DL, /*Depth=*/0, AC, CxtI, DT);
   return mapOverflowResult(LHSRange.unsignedSubMayOverflow(RHSRange));
 }
 
@@ -5690,6 +5697,10 @@ static void setLimitsForSelectPattern(co
 ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo) {
   assert(V->getType()->isIntOrIntVectorTy() && "Expected integer instruction");
 
+  const APInt *C;
+  if (match(V, m_APInt(C)))
+    return ConstantRange(*C);
+
   InstrInfoQuery IIQ(UseInstrInfo);
   unsigned BitWidth = V->getType()->getScalarSizeInBits();
   APInt Lower = APInt(BitWidth, 0);

Modified: llvm/trunk/test/Transforms/InstCombine/and2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/and2.ll?rev=356489&r1=356488&r2=356489&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/and2.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/and2.ll Tue Mar 19 10:53:56 2019
@@ -154,7 +154,7 @@ define i8 @and1_lshr1_is_cmp_eq_0_multiu
 ; CHECK-LABEL: @and1_lshr1_is_cmp_eq_0_multiuse(
 ; CHECK-NEXT:    [[SH:%.*]] = lshr i8 1, %x
 ; CHECK-NEXT:    [[AND:%.*]] = and i8 [[SH]], 1
-; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[SH]], [[AND]]
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i8 [[SH]], [[AND]]
 ; CHECK-NEXT:    ret i8 [[ADD]]
 ;
   %sh = lshr i8 1, %x

Modified: llvm/trunk/test/Transforms/InstCombine/saturating-add-sub.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/saturating-add-sub.ll?rev=356489&r1=356488&r2=356489&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/saturating-add-sub.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/saturating-add-sub.ll Tue Mar 19 10:53:56 2019
@@ -355,7 +355,7 @@ define i8 @test_scalar_uadd_sub_nuw_lost
 define i8 @test_scalar_uadd_urem_no_ov(i8 %a) {
 ; CHECK-LABEL: @test_scalar_uadd_urem_no_ov(
 ; CHECK-NEXT:    [[B:%.*]] = urem i8 [[A:%.*]], 100
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[B]], i8 -100)
+; CHECK-NEXT:    [[R:%.*]] = add nuw nsw i8 [[B]], -100
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %b = urem i8 %a, 100
@@ -379,7 +379,7 @@ define i8 @test_scalar_uadd_urem_known_b
 ; CHECK-LABEL: @test_scalar_uadd_urem_known_bits(
 ; CHECK-NEXT:    [[AA:%.*]] = udiv i8 -66, [[A:%.*]]
 ; CHECK-NEXT:    [[BB:%.*]] = and i8 [[B:%.*]], 63
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[AA]], i8 [[BB]])
+; CHECK-NEXT:    [[R:%.*]] = add nuw i8 [[AA]], [[BB]]
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %aa = udiv i8 190, %a
@@ -768,8 +768,7 @@ define <2 x i8> @test_vector_ssub_neg_nn
 
 define i8 @test_scalar_usub_add_nuw_no_ov(i8 %a) {
 ; CHECK-LABEL: @test_scalar_usub_add_nuw_no_ov(
-; CHECK-NEXT:    [[B:%.*]] = add nuw i8 [[A:%.*]], 10
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[B]], i8 9)
+; CHECK-NEXT:    [[R:%.*]] = add i8 [[A:%.*]], 1
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %b = add nuw i8 %a, 10
@@ -779,9 +778,7 @@ define i8 @test_scalar_usub_add_nuw_no_o
 
 define i8 @test_scalar_usub_add_nuw_eq(i8 %a) {
 ; CHECK-LABEL: @test_scalar_usub_add_nuw_eq(
-; CHECK-NEXT:    [[B:%.*]] = add nuw i8 [[A:%.*]], 10
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[B]], i8 10)
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[A:%.*]]
 ;
   %b = add nuw i8 %a, 10
   %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 10)
@@ -801,9 +798,7 @@ define i8 @test_scalar_usub_add_nuw_may_
 
 define i8 @test_scalar_usub_urem_must_ov(i8 %a) {
 ; CHECK-LABEL: @test_scalar_usub_urem_must_ov(
-; CHECK-NEXT:    [[B:%.*]] = urem i8 [[A:%.*]], 10
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[B]], i8 10)
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 0
 ;
   %b = urem i8 %a, 10
   %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 10)
@@ -828,7 +823,7 @@ define i8 @test_scalar_usub_add_nuw_know
 ; CHECK-LABEL: @test_scalar_usub_add_nuw_known_bits(
 ; CHECK-NEXT:    [[AA:%.*]] = add nuw i8 [[A:%.*]], 10
 ; CHECK-NEXT:    [[BB:%.*]] = and i8 [[B:%.*]], 7
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[AA]], i8 [[BB]])
+; CHECK-NEXT:    [[R:%.*]] = sub nuw i8 [[AA]], [[BB]]
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %aa = add nuw i8 %a, 10
@@ -840,7 +835,7 @@ define i8 @test_scalar_usub_add_nuw_know
 define i8 @test_scalar_usub_add_nuw_inferred(i8 %a) {
 ; CHECK-LABEL: @test_scalar_usub_add_nuw_inferred(
 ; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 10)
-; CHECK-NEXT:    [[R:%.*]] = add i8 [[B]], 9
+; CHECK-NEXT:    [[R:%.*]] = add nuw i8 [[B]], 9
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %b = call i8 @llvm.usub.sat.i8(i8 %a, i8 10)
@@ -850,8 +845,7 @@ define i8 @test_scalar_usub_add_nuw_infe
 
 define <2 x i8> @test_vector_usub_add_nuw_no_ov(<2 x i8> %a) {
 ; CHECK-LABEL: @test_vector_usub_add_nuw_no_ov(
-; CHECK-NEXT:    [[B:%.*]] = add nuw <2 x i8> [[A:%.*]], <i8 10, i8 10>
-; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[B]], <2 x i8> <i8 9, i8 9>)
+; CHECK-NEXT:    [[R:%.*]] = add <2 x i8> [[A:%.*]], <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[R]]
 ;
   %b = add nuw <2 x i8> %a, <i8 10, i8 10>

Modified: llvm/trunk/test/Transforms/InstCombine/uadd-with-overflow.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/uadd-with-overflow.ll?rev=356489&r1=356488&r2=356489&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/uadd-with-overflow.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/uadd-with-overflow.ll Tue Mar 19 10:53:56 2019
@@ -33,9 +33,8 @@ define { i8, i1 } @fold_on_constant_add_
 
 define { i8, i1 } @no_fold_on_constant_add_overflow(i8 %x) {
 ; CHECK-LABEL: @no_fold_on_constant_add_overflow(
-; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[X:%.*]], -56
-; CHECK-NEXT:    [[B:%.*]] = tail call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[A]], i8 56)
-; CHECK-NEXT:    ret { i8, i1 } [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 undef, i1 true }, i8 [[X:%.*]], 0
+; CHECK-NEXT:    ret { i8, i1 } [[TMP1]]
 ;
   %a = add nuw i8 %x, 200
   %b = tail call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %a, i8 56)

Modified: llvm/trunk/test/Transforms/LoopVectorize/X86/small-size.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVectorize/X86/small-size.ll?rev=356489&r1=356488&r2=356489&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LoopVectorize/X86/small-size.ll (original)
+++ llvm/trunk/test/Transforms/LoopVectorize/X86/small-size.ll Tue Mar 19 10:53:56 2019
@@ -81,7 +81,7 @@ define void @example2(i32 %n, i32 %x) op
 ; CHECK-NEXT:    [[N_RND_UP:%.*]] = add nuw nsw i64 [[TMP3]], 4
 ; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[TMP2]], 3
 ; CHECK-NEXT:    [[N_MOD_VF:%.*]] = zext i32 [[TMP4]] to i64
-; CHECK-NEXT:    [[N_VEC:%.*]] = sub nsw i64 [[N_RND_UP]], [[N_MOD_VF]]
+; CHECK-NEXT:    [[N_VEC:%.*]] = sub nuw nsw i64 [[N_RND_UP]], [[N_MOD_VF]]
 ; CHECK-NEXT:    [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i64> undef, i64 [[TMP3]], i32 0
 ; CHECK-NEXT:    [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT1]], <4 x i64> undef, <4 x i32> zeroinitializer
 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]




More information about the llvm-commits mailing list