File tree Expand file tree Collapse file tree 3 files changed +61
-0
lines changed Expand file tree Collapse file tree 3 files changed +61
-0
lines changed Original file line number Diff line number Diff line change @@ -397,6 +397,10 @@ class LLVM_NODISCARD ConstantRange {
397
397
// / Return a new range that is the logical not of the current set.
398
398
ConstantRange inverse () const ;
399
399
400
+ // / Calculate absolute value range. If the original range contains signed
401
+ // / min, then the resulting range will also contain signed min.
402
+ ConstantRange abs () const ;
403
+
400
404
// / Represents whether an operation on the given constant range is known to
401
405
// / always or never overflow.
402
406
enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows };
Original file line number Diff line number Diff line change @@ -1156,6 +1156,37 @@ ConstantRange ConstantRange::inverse() const {
1156
1156
return ConstantRange (Upper, Lower);
1157
1157
}
1158
1158
1159
+ ConstantRange ConstantRange::abs () const {
1160
+ if (isEmptySet ())
1161
+ return getEmpty ();
1162
+
1163
+ if (isSignWrappedSet ()) {
1164
+ APInt Lo;
1165
+ // Check whether the range crosses zero.
1166
+ if (Upper.isStrictlyPositive () || !Lower.isStrictlyPositive ())
1167
+ Lo = APInt::getNullValue (getBitWidth ());
1168
+ else
1169
+ Lo = APIntOps::umin (Lower, -Upper + 1 );
1170
+
1171
+ // SignedMin is included in the result range.
1172
+ return ConstantRange (Lo, APInt::getSignedMinValue (getBitWidth ()) + 1 );
1173
+ }
1174
+
1175
+ APInt SMin = getSignedMin (), SMax = getSignedMax ();
1176
+
1177
+ // All non-negative.
1178
+ if (SMin.isNonNegative ())
1179
+ return *this ;
1180
+
1181
+ // All negative.
1182
+ if (SMax.isNegative ())
1183
+ return ConstantRange (-SMax, -SMin + 1 );
1184
+
1185
+ // Range crosses zero.
1186
+ return ConstantRange (APInt::getNullValue (getBitWidth ()),
1187
+ APIntOps::umax (-SMin, SMax) + 1 );
1188
+ }
1189
+
1159
1190
ConstantRange::OverflowResult ConstantRange::unsignedAddMayOverflow (
1160
1191
const ConstantRange &Other) const {
1161
1192
if (isEmptySet () || Other.isEmptySet ())
Original file line number Diff line number Diff line change @@ -1797,4 +1797,30 @@ TEST_F(ConstantRangeTest, SSubSat) {
1797
1797
});
1798
1798
}
1799
1799
1800
+ TEST_F (ConstantRangeTest, Abs) {
1801
+ unsigned Bits = 4 ;
1802
+ EnumerateConstantRanges (Bits, [&](const ConstantRange &CR) {
1803
+ // We're working with unsigned integers here, because it makes the signed
1804
+ // min case non-wrapping.
1805
+ APInt Min = APInt::getMaxValue (Bits);
1806
+ APInt Max = APInt::getMinValue (Bits);
1807
+ ForeachNumInConstantRange (CR, [&](const APInt &N) {
1808
+ APInt AbsN = N.abs ();
1809
+ if (AbsN.ult (Min))
1810
+ Min = AbsN;
1811
+ if (AbsN.ugt (Max))
1812
+ Max = AbsN;
1813
+ });
1814
+
1815
+ ConstantRange AbsCR = CR.abs ();
1816
+ if (Min.ugt (Max)) {
1817
+ EXPECT_TRUE (AbsCR.isEmptySet ());
1818
+ return ;
1819
+ }
1820
+
1821
+ ConstantRange Exact = ConstantRange::getNonEmpty (Min, Max + 1 );
1822
+ EXPECT_EQ (Exact, AbsCR);
1823
+ });
1824
+ }
1825
+
1800
1826
} // anonymous namespace
You can’t perform that action at this time.
0 commit comments