llvm.org GIT mirror llvm / 49cc96a
[ValueTracking][ConstantRange] Distinguish low/high always overflow In order to fold an always overflowing signed saturating add/sub, we need to know in which direction the always overflow occurs. This patch splits up AlwaysOverflows into AlwaysOverflowsLow and AlwaysOverflowsHigh to pass through this information (but it is not used yet). Differential Revision: https://reviews.llvm.org/D62463 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@361858 91177308-0d34-0410-b5e6-96231b3b80d8 Nikita Popov 1 year, 6 months ago
7 changed file(s) with 80 addition(s) and 38 deletion(s). Raw diff Collapse all Expand all
411411 bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI,
412412 const DominatorTree *DT = nullptr);
413413
414 enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows };
414 enum class OverflowResult {
415 /// Always overflows in the direction of signed/unsigned min value.
416 AlwaysOverflowsLow,
417 /// Always overflows in the direction of signed/unsigned max value.
418 AlwaysOverflowsHigh,
419 /// May or may not overflow.
420 MayOverflow,
421 /// Never overflows.
422 NeverOverflows,
423 };
415424
416425 OverflowResult computeOverflowForUnsignedMul(const Value *LHS,
417426 const Value *RHS,
415415
416416 /// Represents whether an operation on the given constant range is known to
417417 /// always or never overflow.
418 enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows };
418 enum class OverflowResult {
419 /// Always overflows in the direction of signed/unsigned min value.
420 AlwaysOverflowsLow,
421 /// Always overflows in the direction of signed/unsigned max value.
422 AlwaysOverflowsHigh,
423 /// May or may not overflow.
424 MayOverflow,
425 /// Never overflows.
426 NeverOverflows,
427 };
419428
420429 /// Return whether unsigned add of the two ranges always/never overflows.
421430 OverflowResult unsignedAddMayOverflow(const ConstantRange &Other) const;
39913991 switch (OR) {
39923992 case ConstantRange::OverflowResult::MayOverflow:
39933993 return OverflowResult::MayOverflow;
3994 case ConstantRange::OverflowResult::AlwaysOverflows:
3995 return OverflowResult::AlwaysOverflows;
3994 case ConstantRange::OverflowResult::AlwaysOverflowsLow:
3995 return OverflowResult::AlwaysOverflowsLow;
3996 case ConstantRange::OverflowResult::AlwaysOverflowsHigh:
3997 return OverflowResult::AlwaysOverflowsHigh;
39963998 case ConstantRange::OverflowResult::NeverOverflows:
39973999 return OverflowResult::NeverOverflows;
39984000 }
12071207 APInt Min = getUnsignedMin(), Max = getUnsignedMax();
12081208 APInt OtherMin = Other.getUnsignedMin(), OtherMax = Other.getUnsignedMax();
12091209
1210 // a u+ b overflows iff a u> ~b.
1210 // a u+ b overflows high iff a u> ~b.
12111211 if (Min.ugt(~OtherMin))
1212 return OverflowResult::AlwaysOverflows;
1212 return OverflowResult::AlwaysOverflowsHigh;
12131213 if (Max.ugt(~OtherMax))
12141214 return OverflowResult::MayOverflow;
12151215 return OverflowResult::NeverOverflows;
12301230 // a s+ b overflows low iff a s< 0 && b s< 0 && a s< smin - b.
12311231 if (Min.isNonNegative() && OtherMin.isNonNegative() &&
12321232 Min.sgt(SignedMax - OtherMin))
1233 return OverflowResult::AlwaysOverflows;
1233 return OverflowResult::AlwaysOverflowsHigh;
12341234 if (Max.isNegative() && OtherMax.isNegative() &&
12351235 Max.slt(SignedMin - OtherMax))
1236 return OverflowResult::AlwaysOverflows;
1236 return OverflowResult::AlwaysOverflowsLow;
12371237
12381238 if (Max.isNonNegative() && OtherMax.isNonNegative() &&
12391239 Max.sgt(SignedMax - OtherMax))
12531253 APInt Min = getUnsignedMin(), Max = getUnsignedMax();
12541254 APInt OtherMin = Other.getUnsignedMin(), OtherMax = Other.getUnsignedMax();
12551255
1256 // a u- b overflows iff a u< b.
1256 // a u- b overflows low iff a u< b.
12571257 if (Max.ult(OtherMin))
1258 return OverflowResult::AlwaysOverflows;
1258 return OverflowResult::AlwaysOverflowsLow;
12591259 if (Min.ult(OtherMax))
12601260 return OverflowResult::MayOverflow;
12611261 return OverflowResult::NeverOverflows;
12761276 // a s- b overflows low iff a s< 0 && b s>= 0 && a s< smin + b.
12771277 if (Min.isNonNegative() && OtherMax.isNegative() &&
12781278 Min.sgt(SignedMax + OtherMax))
1279 return OverflowResult::AlwaysOverflows;
1279 return OverflowResult::AlwaysOverflowsHigh;
12801280 if (Max.isNegative() && OtherMin.isNonNegative() &&
12811281 Max.slt(SignedMin + OtherMin))
1282 return OverflowResult::AlwaysOverflows;
1282 return OverflowResult::AlwaysOverflowsLow;
12831283
12841284 if (Max.isNonNegative() && OtherMin.isNegative() &&
12851285 Max.sgt(SignedMax + OtherMin))
13021302
13031303 (void) Min.umul_ov(OtherMin, Overflow);
13041304 if (Overflow)
1305 return OverflowResult::AlwaysOverflows;
1305 return OverflowResult::AlwaysOverflowsHigh;
13061306
13071307 (void) Max.umul_ov(OtherMax, Overflow);
13081308 if (Overflow)
20632063 OR = computeOverflowForUnsignedAdd(Arg0, Arg1, II);
20642064 if (OR == OverflowResult::NeverOverflows)
20652065 return BinaryOperator::CreateNUWAdd(Arg0, Arg1);
2066 if (OR == OverflowResult::AlwaysOverflows)
2066 if (OR == OverflowResult::AlwaysOverflowsHigh)
20672067 return replaceInstUsesWith(*II,
20682068 ConstantInt::getAllOnesValue(II->getType()));
20692069 break;
20712071 OR = computeOverflowForUnsignedSub(Arg0, Arg1, II);
20722072 if (OR == OverflowResult::NeverOverflows)
20732073 return BinaryOperator::CreateNUWSub(Arg0, Arg1);
2074 if (OR == OverflowResult::AlwaysOverflows)
2074 if (OR == OverflowResult::AlwaysOverflowsLow)
20752075 return replaceInstUsesWith(*II,
20762076 ConstantInt::getNullValue(II->getType()));
20772077 break;
39923992 switch (computeOverflow(BinaryOp, IsSigned, LHS, RHS, &OrigI)) {
39933993 case OverflowResult::MayOverflow:
39943994 return false;
3995 case OverflowResult::AlwaysOverflows:
3995 case OverflowResult::AlwaysOverflowsLow:
3996 case OverflowResult::AlwaysOverflowsHigh:
39963997 Result = Builder.CreateBinOp(BinaryOp, LHS, RHS);
39973998 Result->takeName(&OrigI);
39983999 Overflow = Builder.getTrue();
14861486
14871487 #define EXPECT_MAY_OVERFLOW(op) \
14881488 EXPECT_EQ(ConstantRange::OverflowResult::MayOverflow, (op))
1489 #define EXPECT_ALWAYS_OVERFLOWS(op) \
1490 EXPECT_EQ(ConstantRange::OverflowResult::AlwaysOverflows, (op))
1489 #define EXPECT_ALWAYS_OVERFLOWS_LOW(op) \
1490 EXPECT_EQ(ConstantRange::OverflowResult::AlwaysOverflowsLow, (op))
1491 #define EXPECT_ALWAYS_OVERFLOWS_HIGH(op) \
1492 EXPECT_EQ(ConstantRange::OverflowResult::AlwaysOverflowsHigh, (op))
14911493 #define EXPECT_NEVER_OVERFLOWS(op) \
14921494 EXPECT_EQ(ConstantRange::OverflowResult::NeverOverflows, (op))
14931495
15201522 ConstantRange C1(APInt(16, 0x0299), APInt(16, 0x0400));
15211523 ConstantRange C2(APInt(16, 0x0300), APInt(16, 0x0400));
15221524 EXPECT_MAY_OVERFLOW(A.unsignedAddMayOverflow(C1));
1523 EXPECT_ALWAYS_OVERFLOWS(A.unsignedAddMayOverflow(C2));
1525 EXPECT_ALWAYS_OVERFLOWS_HIGH(A.unsignedAddMayOverflow(C2));
15241526 EXPECT_MAY_OVERFLOW(C1.unsignedAddMayOverflow(A));
1525 EXPECT_ALWAYS_OVERFLOWS(C2.unsignedAddMayOverflow(A));
1527 EXPECT_ALWAYS_OVERFLOWS_HIGH(C2.unsignedAddMayOverflow(A));
15261528 }
15271529
15281530 TEST_F(ConstantRangeTest, UnsignedSubOverflow) {
15471549 ConstantRange A(APInt(16, 0x0000), APInt(16, 0x0100));
15481550 ConstantRange B(APInt(16, 0x0100), APInt(16, 0x0200));
15491551 EXPECT_NEVER_OVERFLOWS(B.unsignedSubMayOverflow(A));
1550 EXPECT_ALWAYS_OVERFLOWS(A.unsignedSubMayOverflow(B));
1552 EXPECT_ALWAYS_OVERFLOWS_LOW(A.unsignedSubMayOverflow(B));
15511553
15521554 ConstantRange A1(APInt(16, 0x0000), APInt(16, 0x0101));
15531555 ConstantRange B1(APInt(16, 0x0100), APInt(16, 0x0201));
15901592 ConstantRange B5(APInt(16, 0x0299), APInt(16, 0x0400));
15911593 ConstantRange B6(APInt(16, 0x0300), APInt(16, 0x0400));
15921594 EXPECT_MAY_OVERFLOW(A.signedAddMayOverflow(B5));
1593 EXPECT_ALWAYS_OVERFLOWS(A.signedAddMayOverflow(B6));
1595 EXPECT_ALWAYS_OVERFLOWS_HIGH(A.signedAddMayOverflow(B6));
15941596
15951597 ConstantRange C(APInt(16, 0x8200), APInt(16, 0x8300));
15961598 ConstantRange D1(APInt(16, 0xfe00), APInt(16, 0xff00));
16041606 ConstantRange D5(APInt(16, 0xfc00), APInt(16, 0xfd02));
16051607 ConstantRange D6(APInt(16, 0xfc00), APInt(16, 0xfd01));
16061608 EXPECT_MAY_OVERFLOW(C.signedAddMayOverflow(D5));
1607 EXPECT_ALWAYS_OVERFLOWS(C.signedAddMayOverflow(D6));
1609 EXPECT_ALWAYS_OVERFLOWS_LOW(C.signedAddMayOverflow(D6));
16081610
16091611 ConstantRange E(APInt(16, 0xff00), APInt(16, 0x0100));
16101612 EXPECT_NEVER_OVERFLOWS(E.signedAddMayOverflow(E));
16361638 ConstantRange B3(APInt(16, 0xfc00), APInt(16, 0xfd02));
16371639 ConstantRange B4(APInt(16, 0xfc00), APInt(16, 0xfd01));
16381640 EXPECT_MAY_OVERFLOW(A.signedSubMayOverflow(B3));
1639 EXPECT_ALWAYS_OVERFLOWS(A.signedSubMayOverflow(B4));
1641 EXPECT_ALWAYS_OVERFLOWS_HIGH(A.signedSubMayOverflow(B4));
16401642
16411643 ConstantRange C(APInt(16, 0x8200), APInt(16, 0x8300));
16421644 ConstantRange D1(APInt(16, 0x0100), APInt(16, 0x0201));
16461648 ConstantRange D3(APInt(16, 0x0299), APInt(16, 0x0400));
16471649 ConstantRange D4(APInt(16, 0x0300), APInt(16, 0x0400));
16481650 EXPECT_MAY_OVERFLOW(C.signedSubMayOverflow(D3));
1649 EXPECT_ALWAYS_OVERFLOWS(C.signedSubMayOverflow(D4));
1651 EXPECT_ALWAYS_OVERFLOWS_LOW(C.signedSubMayOverflow(D4));
16501652
16511653 ConstantRange E(APInt(16, 0xff00), APInt(16, 0x0100));
16521654 EXPECT_NEVER_OVERFLOWS(E.signedSubMayOverflow(E));
16621664 const ConstantRange &CR2) {
16631665 // Loop over all N1 in CR1 and N2 in CR2 and check whether any of the
16641666 // operations have overflow / have no overflow.
1665 bool RangeHasOverflow = false;
1667 bool RangeHasOverflowLow = false;
1668 bool RangeHasOverflowHigh = false;
16661669 bool RangeHasNoOverflow = false;
16671670 ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
16681671 ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
1669 if (OverflowFn(N1, N2))
1670 RangeHasOverflow = true;
1672 bool IsOverflowHigh;
1673 if (!OverflowFn(IsOverflowHigh, N1, N2)) {
1674 RangeHasNoOverflow = true;
1675 return;
1676 }
1677
1678 if (IsOverflowHigh)
1679 RangeHasOverflowHigh = true;
16711680 else
1672 RangeHasNoOverflow = true;
1681 RangeHasOverflowLow = true;
16731682 });
16741683 });
16751684
16761685 ConstantRange::OverflowResult OR = MayOverflowFn(CR1, CR2);
16771686 switch (OR) {
1678 case ConstantRange::OverflowResult::AlwaysOverflows:
1679 EXPECT_TRUE(RangeHasOverflow);
1687 case ConstantRange::OverflowResult::AlwaysOverflowsLow:
1688 EXPECT_TRUE(RangeHasOverflowLow);
1689 EXPECT_FALSE(RangeHasOverflowHigh);
1690 EXPECT_FALSE(RangeHasNoOverflow);
1691 break;
1692 case ConstantRange::OverflowResult::AlwaysOverflowsHigh:
1693 EXPECT_TRUE(RangeHasOverflowHigh);
1694 EXPECT_FALSE(RangeHasOverflowLow);
16801695 EXPECT_FALSE(RangeHasNoOverflow);
16811696 break;
16821697 case ConstantRange::OverflowResult::NeverOverflows:
1683 EXPECT_FALSE(RangeHasOverflow);
1698 EXPECT_FALSE(RangeHasOverflowLow);
1699 EXPECT_FALSE(RangeHasOverflowHigh);
16841700 EXPECT_TRUE(RangeHasNoOverflow);
16851701 break;
16861702 case ConstantRange::OverflowResult::MayOverflow:
16901706 if (CR1.isEmptySet() || CR2.isEmptySet())
16911707 break;
16921708
1693 EXPECT_TRUE(RangeHasOverflow);
1709 EXPECT_TRUE(RangeHasOverflowLow || RangeHasOverflowHigh);
16941710 EXPECT_TRUE(RangeHasNoOverflow);
16951711 break;
16961712 }
16991715
17001716 TEST_F(ConstantRangeTest, UnsignedAddOverflowExhaustive) {
17011717 TestOverflowExhaustive(
1702 [](const APInt &N1, const APInt &N2) {
1718 [](bool &IsOverflowHigh, const APInt &N1, const APInt &N2) {
17031719 bool Overflow;
17041720 (void) N1.uadd_ov(N2, Overflow);
1721 IsOverflowHigh = true;
17051722 return Overflow;
17061723 },
17071724 [](const ConstantRange &CR1, const ConstantRange &CR2) {
17111728
17121729 TEST_F(ConstantRangeTest, UnsignedSubOverflowExhaustive) {
17131730 TestOverflowExhaustive(
1714 [](const APInt &N1, const APInt &N2) {
1731 [](bool &IsOverflowHigh, const APInt &N1, const APInt &N2) {
17151732 bool Overflow;
17161733 (void) N1.usub_ov(N2, Overflow);
1734 IsOverflowHigh = false;
17171735 return Overflow;
17181736 },
17191737 [](const ConstantRange &CR1, const ConstantRange &CR2) {
17231741
17241742 TEST_F(ConstantRangeTest, UnsignedMulOverflowExhaustive) {
17251743 TestOverflowExhaustive(
1726 [](const APInt &N1, const APInt &N2) {
1744 [](bool &IsOverflowHigh, const APInt &N1, const APInt &N2) {
17271745 bool Overflow;
17281746 (void) N1.umul_ov(N2, Overflow);
1747 IsOverflowHigh = true;
17291748 return Overflow;
17301749 },
17311750 [](const ConstantRange &CR1, const ConstantRange &CR2) {
17351754
17361755 TEST_F(ConstantRangeTest, SignedAddOverflowExhaustive) {
17371756 TestOverflowExhaustive(
1738 [](const APInt &N1, const APInt &N2) {
1757 [](bool &IsOverflowHigh, const APInt &N1, const APInt &N2) {
17391758 bool Overflow;
17401759 (void) N1.sadd_ov(N2, Overflow);
1760 IsOverflowHigh = N1.isNonNegative();
17411761 return Overflow;
17421762 },
17431763 [](const ConstantRange &CR1, const ConstantRange &CR2) {
17471767
17481768 TEST_F(ConstantRangeTest, SignedSubOverflowExhaustive) {
17491769 TestOverflowExhaustive(
1750 [](const APInt &N1, const APInt &N2) {
1770 [](bool &IsOverflowHigh, const APInt &N1, const APInt &N2) {
17511771 bool Overflow;
17521772 (void) N1.ssub_ov(N2, Overflow);
1773 IsOverflowHigh = N1.isNonNegative();
17531774 return Overflow;
17541775 },
17551776 [](const ConstantRange &CR1, const ConstantRange &CR2) {