mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219634 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2061a56b8a
commit
dfe81adbce
@ -945,7 +945,8 @@ public:
|
||||
APInt sdiv_ov(const APInt &RHS, bool &Overflow) const;
|
||||
APInt smul_ov(const APInt &RHS, bool &Overflow) const;
|
||||
APInt umul_ov(const APInt &RHS, bool &Overflow) const;
|
||||
APInt sshl_ov(unsigned Amt, bool &Overflow) const;
|
||||
APInt sshl_ov(const APInt &Amt, bool &Overflow) const;
|
||||
APInt ushl_ov(const APInt &Amt, bool &Overflow) const;
|
||||
|
||||
/// \brief Array-indexing support.
|
||||
///
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -965,11 +965,17 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
|
||||
return Common;
|
||||
|
||||
// (x lshr C1) udiv C2 --> x udiv (C2 << C1)
|
||||
if (Constant *C2 = dyn_cast<Constant>(Op1)) {
|
||||
{
|
||||
Value *X;
|
||||
Constant *C1;
|
||||
if (match(Op0, m_LShr(m_Value(X), m_Constant(C1))))
|
||||
return BinaryOperator::CreateUDiv(X, ConstantExpr::getShl(C2, C1));
|
||||
const APInt *C1, *C2;
|
||||
if (match(Op0, m_LShr(m_Value(X), m_APInt(C1))) &&
|
||||
match(Op1, m_APInt(C2))) {
|
||||
bool Overflow;
|
||||
APInt C2ShlC1 = C2->ushl_ov(*C1, Overflow);
|
||||
if (!Overflow)
|
||||
return BinaryOperator::CreateUDiv(
|
||||
X, ConstantInt::get(X->getType(), C2ShlC1));
|
||||
}
|
||||
}
|
||||
|
||||
// (zext A) udiv (zext B) --> zext (A udiv B)
|
||||
|
@ -132,11 +132,11 @@ define i32 @test15(i32 %a, i32 %b) nounwind {
|
||||
}
|
||||
|
||||
define <2 x i64> @test16(<2 x i64> %x) nounwind {
|
||||
%shr = lshr <2 x i64> %x, <i64 3, i64 5>
|
||||
%div = udiv <2 x i64> %shr, <i64 4, i64 6>
|
||||
%shr = lshr <2 x i64> %x, <i64 5, i64 5>
|
||||
%div = udiv <2 x i64> %shr, <i64 6, i64 6>
|
||||
ret <2 x i64> %div
|
||||
; CHECK-LABEL: @test16(
|
||||
; CHECK-NEXT: udiv <2 x i64> %x, <i64 32, i64 192>
|
||||
; CHECK-NEXT: udiv <2 x i64> %x, <i64 192, i64 192>
|
||||
; CHECK-NEXT: ret <2 x i64>
|
||||
}
|
||||
|
||||
@ -264,3 +264,13 @@ define i32 @test30(i32 %a) {
|
||||
; CHECK-LABEL: @test30(
|
||||
; CHECK-NEXT: ret i32 %a
|
||||
}
|
||||
|
||||
define <2 x i32> @test31(<2 x i32> %x) nounwind {
|
||||
%shr = lshr <2 x i32> %x, <i32 31, i32 31>
|
||||
%div = udiv <2 x i32> %shr, <i32 2147483647, i32 2147483647>
|
||||
ret <2 x i32> %div
|
||||
; CHECK-LABEL: @test31(
|
||||
; CHECK-NEXT: %[[shr:.*]] = lshr <2 x i32> %x, <i32 31, i32 31>
|
||||
; CHECK-NEXT: udiv <2 x i32> %[[shr]], <i32 2147483647, i32 2147483647>
|
||||
; CHECK-NEXT: ret <2 x i32>
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user