diff options
| author | Nikita Popov <nikita.ppv@gmail.com> | 2019-04-21 15:23:05 +0000 |
|---|---|---|
| committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-04-21 15:23:05 +0000 |
| commit | 198ab6013678e35d6b6cbd9cefad84691ff358b2 (patch) | |
| tree | 1f9553127afaab6934d002d68945598c1f638b2b /llvm/lib | |
| parent | dbc3fbafe7cbf10bac30da4d4b6eb6082fed3daa (diff) | |
| download | bcm5719-llvm-198ab6013678e35d6b6cbd9cefad84691ff358b2.tar.gz bcm5719-llvm-198ab6013678e35d6b6cbd9cefad84691ff358b2.zip | |
[ConstantRange] Add saturating add/sub methods
Add support for uadd_sat and friends to ConstantRange, so we can
handle uadd.sat and friends in LVI. The implementation is forwarding
to the corresponding APInt methods with appropriate bounds.
One thing worth pointing out here is that the handling of wrapping
ranges is not maximally accurate. A simple example is that adding 0
to a wrapped range will return a full range, rather than the original
wrapped range. The tests also only check that the non-wrapping
envelope is correct and minimal.
Differential Revision: https://reviews.llvm.org/D60946
llvm-svn: 358855
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/IR/ConstantRange.cpp | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index 7bd14e62dc1..b2bdd0abd9c 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -1099,6 +1099,42 @@ ConstantRange::ashr(const ConstantRange &Other) const { return getNonEmpty(std::move(min), std::move(max)); } +ConstantRange ConstantRange::uadd_sat(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return getEmpty(); + + APInt NewL = getUnsignedMin().uadd_sat(Other.getUnsignedMin()); + APInt NewU = getUnsignedMax().uadd_sat(Other.getUnsignedMax()) + 1; + return getNonEmpty(std::move(NewL), std::move(NewU)); +} + +ConstantRange ConstantRange::sadd_sat(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return getEmpty(); + + APInt NewL = getSignedMin().sadd_sat(Other.getSignedMin()); + APInt NewU = getSignedMax().sadd_sat(Other.getSignedMax()) + 1; + return getNonEmpty(std::move(NewL), std::move(NewU)); +} + +ConstantRange ConstantRange::usub_sat(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return getEmpty(); + + APInt NewL = getUnsignedMin().usub_sat(Other.getUnsignedMax()); + APInt NewU = getUnsignedMax().usub_sat(Other.getUnsignedMin()) + 1; + return getNonEmpty(std::move(NewL), std::move(NewU)); +} + +ConstantRange ConstantRange::ssub_sat(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return getEmpty(); + + APInt NewL = getSignedMin().ssub_sat(Other.getSignedMax()); + APInt NewU = getSignedMax().ssub_sat(Other.getSignedMin()) + 1; + return getNonEmpty(std::move(NewL), std::move(NewU)); +} + ConstantRange ConstantRange::inverse() const { if (isFullSet()) return getEmpty(); |

