diff options
| author | Philip Reames <listmail@philipreames.com> | 2016-12-01 20:08:47 +0000 |
|---|---|---|
| committer | Philip Reames <listmail@philipreames.com> | 2016-12-01 20:08:47 +0000 |
| commit | 4d00af1bde7a9db210fe80bb7207832112ef9394 (patch) | |
| tree | 90852477eaa4e8038de7aea741ae1ac4b205b316 /llvm/lib/IR/ConstantRange.cpp | |
| parent | 2c01af590457dad514c8998f8c950c15319e2077 (diff) | |
| download | bcm5719-llvm-4d00af1bde7a9db210fe80bb7207832112ef9394.tar.gz bcm5719-llvm-4d00af1bde7a9db210fe80bb7207832112ef9394.zip | |
Factor out common parts of LVI and Float2Int into ConstantRange [NFCI]
This just extracts out the transfer rules for constant ranges into a single shared point. As it happens, neither bit of code actually overlaps in terms of the handled operators, but with this change that could easily be tweaked in the future.
I also want to have this separated out to make experimenting with a eager value info implementation and possibly a ValueTracking-like fixed depth recursion peephole version. There's no reason all four of these can't share a common implementation which reduces the chances of bugs.
Differential Revision: https://reviews.llvm.org/D27294
llvm-svn: 288413
Diffstat (limited to 'llvm/lib/IR/ConstantRange.cpp')
| -rw-r--r-- | llvm/lib/IR/ConstantRange.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index e188c8074ad..a85ad465317 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -534,6 +534,49 @@ ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const { return ConstantRange(L, U); } +ConstantRange ConstantRange::castOp(Instruction::CastOps CastOp, + uint32_t ResultBitWidth) const { + switch (CastOp) { + default: + llvm_unreachable("unsupported cast type"); + case Instruction::Trunc: + return truncate(ResultBitWidth); + case Instruction::SExt: + return signExtend(ResultBitWidth); + case Instruction::ZExt: + return zeroExtend(ResultBitWidth); + case Instruction::BitCast: + return *this; + case Instruction::FPToUI: + case Instruction::FPToSI: + if (getBitWidth() == ResultBitWidth) + return *this; + else + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + case Instruction::UIToFP: { + // TODO: use input range if available + auto BW = getBitWidth(); + APInt Min = APInt::getMinValue(BW).zextOrSelf(ResultBitWidth); + APInt Max = APInt::getMaxValue(BW).zextOrSelf(ResultBitWidth); + return ConstantRange(Min, Max); + } + case Instruction::SIToFP: { + // TODO: use input range if available + auto BW = getBitWidth(); + APInt SMin = APInt::getSignedMinValue(BW).sextOrSelf(ResultBitWidth); + APInt SMax = APInt::getSignedMaxValue(BW).sextOrSelf(ResultBitWidth); + return ConstantRange(SMin, SMax); + } + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::IntToPtr: + case Instruction::PtrToInt: + case Instruction::AddrSpaceCast: + // Conservatively return full set. + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + }; +} + /// zeroExtend - Return a new range in the specified integer type, which must /// be strictly larger than the current type. The returned range will /// correspond to the possible range of values as if the source range had been @@ -653,6 +696,42 @@ ConstantRange ConstantRange::sextOrTrunc(uint32_t DstTySize) const { return *this; } +ConstantRange ConstantRange::binaryOp(Instruction::BinaryOps BinOp, + const ConstantRange &Other) const { + assert(BinOp >= Instruction::BinaryOpsBegin && + BinOp < Instruction::BinaryOpsEnd && "Binary operators only!"); + + switch (BinOp) { + case Instruction::Add: + return add(Other); + case Instruction::Sub: + return sub(Other); + case Instruction::Mul: + return multiply(Other); + case Instruction::UDiv: + return udiv(Other); + case Instruction::Shl: + return shl(Other); + case Instruction::LShr: + return lshr(Other); + case Instruction::And: + return binaryAnd(Other); + case Instruction::Or: + return binaryOr(Other); + // Note: floating point operations applied to abstract ranges are just + // ideal integer operations with a lossy representation + case Instruction::FAdd: + return add(Other); + case Instruction::FSub: + return sub(Other); + case Instruction::FMul: + return multiply(Other); + default: + // Conservatively return full set. + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + } +} + ConstantRange ConstantRange::add(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) |

