diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-10-13 21:48:30 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-10-13 21:48:30 +0000 |
commit | a252138942d8d48eb31234e0da09d3d97cb6abad (patch) | |
tree | eaabf3357117fd540cd950b358b119366ae26c27 /llvm/lib/Support/APInt.cpp | |
parent | a562b46db736bdaa74e7c52a1eb7415561613836 (diff) | |
download | bcm5719-llvm-a252138942d8d48eb31234e0da09d3d97cb6abad.tar.gz bcm5719-llvm-a252138942d8d48eb31234e0da09d3d97cb6abad.zip |
InstCombine: Don't miscompile (x lshr C1) udiv C2
We have a transform that changes:
(x lshr C1) udiv C2
into:
x udiv (C2 << C1)
However, it is unsafe to do so if C2 << C1 discards any of C2's bits.
This fixes PR21255.
llvm-svn: 219634
Diffstat (limited to 'llvm/lib/Support/APInt.cpp')
-rw-r--r-- | llvm/lib/Support/APInt.cpp | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 02778b2fc7c..c20eeb26948 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -2064,19 +2064,29 @@ APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const { return Res; } -APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) const { - Overflow = ShAmt >= getBitWidth(); +APInt APInt::sshl_ov(const APInt &ShAmt, bool &Overflow) const { + Overflow = ShAmt.uge(getBitWidth()); if (Overflow) - ShAmt = getBitWidth()-1; + return APInt(BitWidth, 0); if (isNonNegative()) // Don't allow sign change. - Overflow = ShAmt >= countLeadingZeros(); + Overflow = ShAmt.uge(countLeadingZeros()); else - Overflow = ShAmt >= countLeadingOnes(); + Overflow = ShAmt.uge(countLeadingOnes()); return *this << ShAmt; } +APInt APInt::ushl_ov(const APInt &ShAmt, bool &Overflow) const { + Overflow = ShAmt.uge(getBitWidth()); + if (Overflow) + return APInt(BitWidth, 0); + + Overflow = ShAmt.ugt(countLeadingZeros()); + + return *this << ShAmt; +} + |