diff options
author | Joey Gouly <joey.gouly@gmail.com> | 2017-02-07 11:58:22 +0000 |
---|---|---|
committer | Joey Gouly <joey.gouly@gmail.com> | 2017-02-07 11:58:22 +0000 |
commit | 51c0ae5e512138fd8257b853f37cedc7fbd193d3 (patch) | |
tree | 2f44c21e4527a8639d3c9a4a7e01531070d02671 /llvm/lib/Support/APInt.cpp | |
parent | d588b0f5254a971b213648d7f7ab7579f10ba7a9 (diff) | |
download | bcm5719-llvm-51c0ae5e512138fd8257b853f37cedc7fbd193d3.tar.gz bcm5719-llvm-51c0ae5e512138fd8257b853f37cedc7fbd193d3.zip |
[APInt] Fix rotl/rotr when the shift amount is greater than the total bit width.
Review: https://reviews.llvm.org/D27749
llvm-svn: 294295
Diffstat (limited to 'llvm/lib/Support/APInt.cpp')
-rw-r--r-- | llvm/lib/Support/APInt.cpp | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 7b3be916f31..7e17e42dc91 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -1252,8 +1252,21 @@ APInt APInt::shlSlowCase(unsigned shiftAmt) const { return Result; } +// Calculate the rotate amount modulo the bit width. +static unsigned rotateModulo(unsigned BitWidth, const APInt &rotateAmt) { + unsigned rotBitWidth = rotateAmt.getBitWidth(); + APInt rot = rotateAmt; + if (rotBitWidth < BitWidth) { + // Extend the rotate APInt, so that the urem doesn't divide by 0. + // e.g. APInt(1, 32) would give APInt(1, 0). + rot = rotateAmt.zext(BitWidth); + } + rot = rot.urem(APInt(rot.getBitWidth(), BitWidth)); + return rot.getLimitedValue(BitWidth); +} + APInt APInt::rotl(const APInt &rotateAmt) const { - return rotl((unsigned)rotateAmt.getLimitedValue(BitWidth)); + return rotl(rotateModulo(BitWidth, rotateAmt)); } APInt APInt::rotl(unsigned rotateAmt) const { @@ -1264,7 +1277,7 @@ APInt APInt::rotl(unsigned rotateAmt) const { } APInt APInt::rotr(const APInt &rotateAmt) const { - return rotr((unsigned)rotateAmt.getLimitedValue(BitWidth)); + return rotr(rotateModulo(BitWidth, rotateAmt)); } APInt APInt::rotr(unsigned rotateAmt) const { |