llvm.org GIT mirror llvm / 0393ba9
[ConstantRange] Add abs() support Add support for abs() to ConstantRange. This will allow to handle SPF_ABS select flavor in LVI and will also come in handy as a primitive for the srem implementation. The implementation is slightly tricky, because a) abs of signed min is signed min and b) sign-wrapped ranges may have an abs() that is smaller than a full range, so we need to explicitly handle them. Differential Revision: https://reviews.llvm.org/D61084 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359321 91177308-0d34-0410-b5e6-96231b3b80d8 Nikita Popov 1 year, 7 months ago
3 changed file(s) with 61 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
396396 /// Return a new range that is the logical not of the current set.
397397 ConstantRange inverse() const;
398398
399 /// Calculate absolute value range. If the original range contains signed
400 /// min, then the resulting range will also contain signed min.
401 ConstantRange abs() const;
402
399403 /// Represents whether an operation on the given constant range is known to
400404 /// always or never overflow.
401405 enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows };
11551155 return ConstantRange(Upper, Lower);
11561156 }
11571157
1158 ConstantRange ConstantRange::abs() const {
1159 if (isEmptySet())
1160 return getEmpty();
1161
1162 if (isSignWrappedSet()) {
1163 APInt Lo;
1164 // Check whether the range crosses zero.
1165 if (Upper.isStrictlyPositive() || !Lower.isStrictlyPositive())
1166 Lo = APInt::getNullValue(getBitWidth());
1167 else
1168 Lo = APIntOps::umin(Lower, -Upper + 1);
1169
1170 // SignedMin is included in the result range.
1171 return ConstantRange(Lo, APInt::getSignedMinValue(getBitWidth()) + 1);
1172 }
1173
1174 APInt SMin = getSignedMin(), SMax = getSignedMax();
1175
1176 // All non-negative.
1177 if (SMin.isNonNegative())
1178 return *this;
1179
1180 // All negative.
1181 if (SMax.isNegative())
1182 return ConstantRange(-SMax, -SMin + 1);
1183
1184 // Range crosses zero.
1185 return ConstantRange(APInt::getNullValue(getBitWidth()),
1186 APIntOps::umax(-SMin, SMax) + 1);
1187 }
1188
11581189 ConstantRange::OverflowResult ConstantRange::unsignedAddMayOverflow(
11591190 const ConstantRange &Other) const {
11601191 if (isEmptySet() || Other.isEmptySet())
17961796 });
17971797 }
17981798
1799 TEST_F(ConstantRangeTest, Abs) {
1800 unsigned Bits = 4;
1801 EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
1802 // We're working with unsigned integers here, because it makes the signed
1803 // min case non-wrapping.
1804 APInt Min = APInt::getMaxValue(Bits);
1805 APInt Max = APInt::getMinValue(Bits);
1806 ForeachNumInConstantRange(CR, [&](const APInt &N) {
1807 APInt AbsN = N.abs();
1808 if (AbsN.ult(Min))
1809 Min = AbsN;
1810 if (AbsN.ugt(Max))
1811 Max = AbsN;
1812 });
1813
1814 ConstantRange AbsCR = CR.abs();
1815 if (Min.ugt(Max)) {
1816 EXPECT_TRUE(AbsCR.isEmptySet());
1817 return;
1818 }
1819
1820 ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
1821 EXPECT_EQ(Exact, AbsCR);
1822 });
1823 }
1824
17991825 } // anonymous namespace