llvm.org GIT mirror llvm / e64a828
[ConstantRange] Add support of mul in makeGuaranteedNoWrapRegion. Summary: This is trying to add support for r334428. Reviewers: sanjoy Subscribers: jlebar, hiraditya, bixia, llvm-commits Differential Revision: https://reviews.llvm.org/D48399 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@335646 91177308-0d34-0410-b5e6-96231b3b80d8 Tim Shen 1 year, 3 months ago
2 changed file(s) with 157 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
254254 APInt::getSignedMinValue(BitWidth) + SignedMin));
255255 }
256256 return Result;
257 case Instruction::Mul: {
258 if (NoWrapKind == (OBO::NoSignedWrap | OBO::NoUnsignedWrap)) {
259 return SubsetIntersect(
260 makeGuaranteedNoWrapRegion(BinOp, Other, OBO::NoSignedWrap),
261 makeGuaranteedNoWrapRegion(BinOp, Other, OBO::NoUnsignedWrap));
262 }
263
264 // Equivalent to calling makeGuaranteedNoWrapRegion() on [V, V+1).
265 const bool Unsigned = NoWrapKind == OBO::NoUnsignedWrap;
266 const auto makeSingleValueRegion = [Unsigned,
267 BitWidth](APInt V) -> ConstantRange {
268 // Handle special case for 0, -1 and 1. See the last for reason why we
269 // specialize -1 and 1.
270 if (V == 0 || V.isOneValue())
271 return ConstantRange(BitWidth, true);
272
273 APInt MinValue, MaxValue;
274 if (Unsigned) {
275 MinValue = APInt::getMinValue(BitWidth);
276 MaxValue = APInt::getMaxValue(BitWidth);
277 } else {
278 MinValue = APInt::getSignedMinValue(BitWidth);
279 MaxValue = APInt::getSignedMaxValue(BitWidth);
280 }
281 // e.g. Returning [-127, 127], represented as [-127, -128).
282 if (!Unsigned && V.isAllOnesValue())
283 return ConstantRange(-MaxValue, MinValue);
284
285 APInt Lower, Upper;
286 if (!Unsigned && V.isNegative()) {
287 Lower = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::UP);
288 Upper = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::DOWN);
289 } else if (Unsigned) {
290 Lower = APIntOps::RoundingUDiv(MinValue, V, APInt::Rounding::UP);
291 Upper = APIntOps::RoundingUDiv(MaxValue, V, APInt::Rounding::DOWN);
292 } else {
293 Lower = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::UP);
294 Upper = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::DOWN);
295 }
296 if (Unsigned) {
297 Lower = Lower.zextOrSelf(BitWidth);
298 Upper = Upper.zextOrSelf(BitWidth);
299 } else {
300 Lower = Lower.sextOrSelf(BitWidth);
301 Upper = Upper.sextOrSelf(BitWidth);
302 }
303 // ConstantRange ctor take a half inclusive interval [Lower, Upper + 1).
304 // Upper + 1 is guanranteed not to overflow, because |divisor| > 1. 0, -1,
305 // and 1 are already handled as special cases.
306 return ConstantRange(Lower, Upper + 1);
307 };
308
309 if (Unsigned)
310 return makeSingleValueRegion(Other.getUnsignedMax());
311
312 return SubsetIntersect(makeSingleValueRegion(Other.getSignedMin()),
313 makeSingleValueRegion(Other.getSignedMax()));
314 }
257315 }
258316 }
259317
10201020 EXPECT_EQ(RHS, APInt(32, -1));
10211021 }
10221022
1023 TEST(ConstantRange, MakeGuaranteedNoWrapRegionMulUnsignedSingleValue) {
1024 typedef OverflowingBinaryOperator OBO;
1025
1026 for (uint64_t I = std::numeric_limits::min();
1027 I <= std::numeric_limits::max(); I++) {
1028 auto Range = ConstantRange::makeGuaranteedNoWrapRegion(
1029 Instruction::Mul, ConstantRange(APInt(8, I), APInt(8, I + 1)),
1030 OBO::NoUnsignedWrap);
1031
1032 for (uint64_t V = std::numeric_limits::min();
1033 V <= std::numeric_limits::max(); V++) {
1034 bool Overflow;
1035 (void)APInt(8, I).umul_ov(APInt(8, V), Overflow);
1036 EXPECT_EQ(!Overflow, Range.contains(APInt(8, V)));
1037 }
1038 }
1039 }
1040
1041 TEST(ConstantRange, MakeGuaranteedNoWrapRegionMulSignedSingleValue) {
1042 typedef OverflowingBinaryOperator OBO;
1043
1044 for (int64_t I = std::numeric_limits::min();
1045 I <= std::numeric_limits::max(); I++) {
1046 auto Range = ConstantRange::makeGuaranteedNoWrapRegion(
1047 Instruction::Mul,
1048 ConstantRange(APInt(8, I, /*isSigned=*/true),
1049 APInt(8, I + 1, /*isSigned=*/true)),
1050 OBO::NoSignedWrap);
1051
1052 for (int64_t V = std::numeric_limits::min();
1053 V <= std::numeric_limits::max(); V++) {
1054 bool Overflow;
1055 (void)APInt(8, I, /*isSigned=*/true)
1056 .smul_ov(APInt(8, V, /*isSigned=*/true), Overflow);
1057 EXPECT_EQ(!Overflow, Range.contains(APInt(8, V, /*isSigned=*/true)));
1058 }
1059 }
1060 }
1061
1062 TEST(ConstantRange, MakeGuaranteedNoWrapRegionMulUnsignedAndSignedSingleValue) {
1063 typedef OverflowingBinaryOperator OBO;
1064
1065 for (uint64_t I = std::numeric_limits::min();
1066 I <= std::numeric_limits::max(); I++) {
1067 auto Range = ConstantRange::makeGuaranteedNoWrapRegion(
1068 Instruction::Mul, ConstantRange(APInt(8, I), APInt(8, I + 1)),
1069 OBO::NoUnsignedWrap | OBO::NoSignedWrap);
1070
1071 for (uint64_t V = std::numeric_limits::min();
1072 V <= std::numeric_limits::max(); V++) {
1073 bool UOverflow;
1074 (void)APInt(8, I).umul_ov(APInt(8, V), UOverflow);
1075 bool SOverflow;
1076 (void)APInt(8, I).smul_ov(APInt(8, V), SOverflow);
1077 EXPECT_EQ(!(UOverflow || SOverflow), Range.contains(APInt(8, V)));
1078 }
1079 }
1080 }
1081
1082 TEST(ConstantRange, MakeGuaranteedNoWrapRegionMulUnsignedRange) {
1083 typedef OverflowingBinaryOperator OBO;
1084
1085 for (uint64_t Lo = std::numeric_limits::min();
1086 Lo <= std::numeric_limits::max(); Lo++) {
1087 for (uint64_t Hi = Lo; Hi <= std::numeric_limits::max(); Hi++) {
1088 EXPECT_EQ(
1089 ConstantRange::makeGuaranteedNoWrapRegion(
1090 Instruction::Mul, ConstantRange(APInt(8, Lo), APInt(8, Hi + 1)),
1091 OBO::NoUnsignedWrap),
1092 ConstantRange::makeGuaranteedNoWrapRegion(
1093 Instruction::Mul, ConstantRange(APInt(8, Hi), APInt(8, Hi + 1)),
1094 OBO::NoUnsignedWrap));
1095 }
1096 }
1097 }
1098
1099 TEST(ConstantRange, MakeGuaranteedNoWrapRegionMulSignedRange) {
1100 typedef OverflowingBinaryOperator OBO;
1101
1102 int Lo = -12, Hi = 16;
1103 auto Range = ConstantRange::makeGuaranteedNoWrapRegion(
1104 Instruction::Mul,
1105 ConstantRange(APInt(8, Lo, /*isSigned=*/true),
1106 APInt(8, Hi + 1, /*isSigned=*/true)),
1107 OBO::NoSignedWrap);
1108
1109 for (int64_t V = std::numeric_limits::min();
1110 V <= std::numeric_limits::max(); V++) {
1111 bool AnyOverflow = false;
1112 for (int64_t I = Lo; I <= Hi; I++) {
1113 bool Overflow;
1114 (void)APInt(8, I, /*isSigned=*/true)
1115 .smul_ov(APInt(8, V, /*isSigned=*/true), Overflow);
1116 AnyOverflow |= Overflow;
1117 }
1118 EXPECT_EQ(!AnyOverflow, Range.contains(APInt(8, V, /*isSigned=*/true)));
1119 }
1120 }
1121
10231122 } // anonymous namespace