mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
InstCombine, InstSimplify: (%X /s C1) /s C2 isn't always 0 when C1 * C2 overflow
consider: C1 = INT_MIN C2 = -1 C1 * C2 overflows without a doubt but consider the following: %x = i32 INT_MIN This means that (%X /s C1) is 1 and (%X /s C1) /s C2 is -1. N. B. Move the unsigned version of this transform to InstSimplify, it doesn't create any new instructions. This fixes PR21243. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219567 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2af441e26e
commit
9043f74acb
@ -1057,6 +1057,16 @@ static Value *SimplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
|
|||||||
(!isSigned && match(Op0, m_URem(m_Value(), m_Specific(Op1)))))
|
(!isSigned && match(Op0, m_URem(m_Value(), m_Specific(Op1)))))
|
||||||
return Constant::getNullValue(Op0->getType());
|
return Constant::getNullValue(Op0->getType());
|
||||||
|
|
||||||
|
// (X /u C1) /u C2 -> 0 if C1 * C2 overflow
|
||||||
|
ConstantInt *C1, *C2;
|
||||||
|
if (!isSigned && match(Op0, m_UDiv(m_Value(X), m_ConstantInt(C1))) &&
|
||||||
|
match(Op1, m_ConstantInt(C2))) {
|
||||||
|
bool Overflow;
|
||||||
|
C1->getValue().umul_ov(C2->getValue(), Overflow);
|
||||||
|
if (Overflow)
|
||||||
|
return Constant::getNullValue(Op0->getType());
|
||||||
|
}
|
||||||
|
|
||||||
// If the operation is with the result of a select instruction, check whether
|
// If the operation is with the result of a select instruction, check whether
|
||||||
// operating on either branch of the select always yields the same value.
|
// operating on either branch of the select always yields the same value.
|
||||||
if (isa<SelectInst>(Op0) || isa<SelectInst>(Op1))
|
if (isa<SelectInst>(Op0) || isa<SelectInst>(Op1))
|
||||||
|
@ -727,11 +727,10 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) {
|
|||||||
// (X / C1) / C2 -> X / (C1*C2)
|
// (X / C1) / C2 -> X / (C1*C2)
|
||||||
if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode())
|
if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode())
|
||||||
if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
|
if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
|
||||||
if (MultiplyOverflows(RHS, LHSRHS,
|
if (!MultiplyOverflows(RHS, LHSRHS,
|
||||||
I.getOpcode() == Instruction::SDiv))
|
I.getOpcode() == Instruction::SDiv))
|
||||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0),
|
||||||
return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0),
|
ConstantExpr::getMul(RHS, LHSRHS));
|
||||||
ConstantExpr::getMul(RHS, LHSRHS));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *X;
|
Value *X;
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
; RUN: opt < %s -instcombine -S | grep "ret i.* 0" | count 2
|
|
||||||
; PR2048
|
|
||||||
|
|
||||||
define i32 @i(i32 %a) {
|
|
||||||
%tmp1 = sdiv i32 %a, -1431655765
|
|
||||||
%tmp2 = sdiv i32 %tmp1, 3
|
|
||||||
ret i32 %tmp2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i8 @j(i8 %a) {
|
|
||||||
%tmp1 = sdiv i8 %a, 64
|
|
||||||
%tmp2 = sdiv i8 %tmp1, 3
|
|
||||||
ret i8 %tmp2
|
|
||||||
}
|
|
@ -42,3 +42,19 @@ define i32 @shift5(i32 %A, i32 %B) {
|
|||||||
%D = ashr i32 %C, %B
|
%D = ashr i32 %C, %B
|
||||||
ret i32 %D
|
ret i32 %D
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @div1(
|
||||||
|
; CHECK: ret i32 0
|
||||||
|
define i32 @div1(i32 %V) {
|
||||||
|
%A = udiv i32 %V, -2147483648
|
||||||
|
%B = udiv i32 %A, -2147483648
|
||||||
|
ret i32 %B
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @div2(
|
||||||
|
; CHECK-NOT: ret i32 0
|
||||||
|
define i32 @div2(i32 %V) {
|
||||||
|
%A = sdiv i32 %V, -1
|
||||||
|
%B = sdiv i32 %A, -2147483648
|
||||||
|
ret i32 %B
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user