diff options
author | Tim Shen <timshen91@gmail.com> | 2018-06-26 18:54:10 +0000 |
---|---|---|
committer | Tim Shen <timshen91@gmail.com> | 2018-06-26 18:54:10 +0000 |
commit | b32823cbe979a8115adb097d6ef0017b0e9a7f63 (patch) | |
tree | e1f3f170d78c3713e8b0b6e2309c036dccadcf9d /llvm/lib | |
parent | 2c1a570aabc184e93f160992c3fe3eab8f884f74 (diff) | |
download | bcm5719-llvm-b32823cbe979a8115adb097d6ef0017b0e9a7f63.tar.gz bcm5719-llvm-b32823cbe979a8115adb097d6ef0017b0e9a7f63.zip |
[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
llvm-svn: 335646
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/IR/ConstantRange.cpp | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index 157473f84f2..86cd24b2e31 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -255,6 +255,64 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp, APInt::getSignedMinValue(BitWidth) + SignedMin)); } return Result; + case Instruction::Mul: { + if (NoWrapKind == (OBO::NoSignedWrap | OBO::NoUnsignedWrap)) { + return SubsetIntersect( + makeGuaranteedNoWrapRegion(BinOp, Other, OBO::NoSignedWrap), + makeGuaranteedNoWrapRegion(BinOp, Other, OBO::NoUnsignedWrap)); + } + + // Equivalent to calling makeGuaranteedNoWrapRegion() on [V, V+1). + const bool Unsigned = NoWrapKind == OBO::NoUnsignedWrap; + const auto makeSingleValueRegion = [Unsigned, + BitWidth](APInt V) -> ConstantRange { + // Handle special case for 0, -1 and 1. See the last for reason why we + // specialize -1 and 1. + if (V == 0 || V.isOneValue()) + return ConstantRange(BitWidth, true); + + APInt MinValue, MaxValue; + if (Unsigned) { + MinValue = APInt::getMinValue(BitWidth); + MaxValue = APInt::getMaxValue(BitWidth); + } else { + MinValue = APInt::getSignedMinValue(BitWidth); + MaxValue = APInt::getSignedMaxValue(BitWidth); + } + // e.g. Returning [-127, 127], represented as [-127, -128). + if (!Unsigned && V.isAllOnesValue()) + return ConstantRange(-MaxValue, MinValue); + + APInt Lower, Upper; + if (!Unsigned && V.isNegative()) { + Lower = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::UP); + Upper = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::DOWN); + } else if (Unsigned) { + Lower = APIntOps::RoundingUDiv(MinValue, V, APInt::Rounding::UP); + Upper = APIntOps::RoundingUDiv(MaxValue, V, APInt::Rounding::DOWN); + } else { + Lower = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::UP); + Upper = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::DOWN); + } + if (Unsigned) { + Lower = Lower.zextOrSelf(BitWidth); + Upper = Upper.zextOrSelf(BitWidth); + } else { + Lower = Lower.sextOrSelf(BitWidth); + Upper = Upper.sextOrSelf(BitWidth); + } + // ConstantRange ctor take a half inclusive interval [Lower, Upper + 1). + // Upper + 1 is guanranteed not to overflow, because |divisor| > 1. 0, -1, + // and 1 are already handled as special cases. + return ConstantRange(Lower, Upper + 1); + }; + + if (Unsigned) + return makeSingleValueRegion(Other.getUnsignedMax()); + + return SubsetIntersect(makeSingleValueRegion(Other.getSignedMin()), + makeSingleValueRegion(Other.getSignedMax())); + } } } |