forked from OSchip/llvm-project
Fix PR13991: legalizing an overflowing multiplication operation is harder than
the add/sub case since in the case of multiplication you also have to check that the operation in the larger type did not overflow. llvm-svn: 165017
This commit is contained in:
parent
a99c35702d
commit
f97cb15aee
|
@ -644,8 +644,9 @@ SDValue DAGTypeLegalizer::PromoteIntRes_XMULO(SDNode *N, unsigned ResNo) {
|
||||||
EVT SmallVT = LHS.getValueType();
|
EVT SmallVT = LHS.getValueType();
|
||||||
|
|
||||||
// To determine if the result overflowed in a larger type, we extend the
|
// To determine if the result overflowed in a larger type, we extend the
|
||||||
// input to the larger type, do the multiply, then check the high bits of
|
// input to the larger type, do the multiply (checking if it overflows),
|
||||||
// the result to see if the overflow happened.
|
// then also check the high bits of the result to see if overflow happened
|
||||||
|
// there.
|
||||||
if (N->getOpcode() == ISD::SMULO) {
|
if (N->getOpcode() == ISD::SMULO) {
|
||||||
LHS = SExtPromotedInteger(LHS);
|
LHS = SExtPromotedInteger(LHS);
|
||||||
RHS = SExtPromotedInteger(RHS);
|
RHS = SExtPromotedInteger(RHS);
|
||||||
|
@ -653,24 +654,31 @@ SDValue DAGTypeLegalizer::PromoteIntRes_XMULO(SDNode *N, unsigned ResNo) {
|
||||||
LHS = ZExtPromotedInteger(LHS);
|
LHS = ZExtPromotedInteger(LHS);
|
||||||
RHS = ZExtPromotedInteger(RHS);
|
RHS = ZExtPromotedInteger(RHS);
|
||||||
}
|
}
|
||||||
SDValue Mul = DAG.getNode(ISD::MUL, DL, LHS.getValueType(), LHS, RHS);
|
SDVTList VTs = DAG.getVTList(LHS.getValueType(), N->getValueType(1));
|
||||||
|
SDValue Mul = DAG.getNode(N->getOpcode(), DL, VTs, LHS, RHS);
|
||||||
|
|
||||||
// Overflow occurred iff the high part of the result does not
|
// Overflow occurred if it occurred in the larger type, or if the high part
|
||||||
// zero/sign-extend the low part.
|
// of the result does not zero/sign-extend the low part. Check this second
|
||||||
|
// possibility first.
|
||||||
SDValue Overflow;
|
SDValue Overflow;
|
||||||
if (N->getOpcode() == ISD::UMULO) {
|
if (N->getOpcode() == ISD::UMULO) {
|
||||||
// Unsigned overflow occurred iff the high part is non-zero.
|
// Unsigned overflow occurred if the high part is non-zero.
|
||||||
SDValue Hi = DAG.getNode(ISD::SRL, DL, Mul.getValueType(), Mul,
|
SDValue Hi = DAG.getNode(ISD::SRL, DL, Mul.getValueType(), Mul,
|
||||||
DAG.getIntPtrConstant(SmallVT.getSizeInBits()));
|
DAG.getIntPtrConstant(SmallVT.getSizeInBits()));
|
||||||
Overflow = DAG.getSetCC(DL, N->getValueType(1), Hi,
|
Overflow = DAG.getSetCC(DL, N->getValueType(1), Hi,
|
||||||
DAG.getConstant(0, Hi.getValueType()), ISD::SETNE);
|
DAG.getConstant(0, Hi.getValueType()), ISD::SETNE);
|
||||||
} else {
|
} else {
|
||||||
// Signed overflow occurred iff the high part does not sign extend the low.
|
// Signed overflow occurred if the high part does not sign extend the low.
|
||||||
SDValue SExt = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, Mul.getValueType(),
|
SDValue SExt = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, Mul.getValueType(),
|
||||||
Mul, DAG.getValueType(SmallVT));
|
Mul, DAG.getValueType(SmallVT));
|
||||||
Overflow = DAG.getSetCC(DL, N->getValueType(1), SExt, Mul, ISD::SETNE);
|
Overflow = DAG.getSetCC(DL, N->getValueType(1), SExt, Mul, ISD::SETNE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The only other way for overflow to occur is if the multiplication in the
|
||||||
|
// larger type itself overflowed.
|
||||||
|
Overflow = DAG.getNode(ISD::OR, DL, N->getValueType(1), Overflow,
|
||||||
|
SDValue(Mul.getNode(), 1));
|
||||||
|
|
||||||
// Use the calculated overflow everywhere.
|
// Use the calculated overflow everywhere.
|
||||||
ReplaceValueWith(SDValue(N, 1), Overflow);
|
ReplaceValueWith(SDValue(N, 1), Overflow);
|
||||||
return Mul;
|
return Mul;
|
||||||
|
|
|
@ -67,3 +67,17 @@ entry:
|
||||||
; CHECK: mull
|
; CHECK: mull
|
||||||
; CHECK-NEXT: ret
|
; CHECK-NEXT: ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare { i63, i1 } @llvm.smul.with.overflow.i63(i63, i63) nounwind readnone
|
||||||
|
|
||||||
|
define i1 @test5() nounwind {
|
||||||
|
entry:
|
||||||
|
%res = call { i63, i1 } @llvm.smul.with.overflow.i63(i63 4, i63 4611686018427387903)
|
||||||
|
%sum = extractvalue { i63, i1 } %res, 0
|
||||||
|
%overflow = extractvalue { i63, i1 } %res, 1
|
||||||
|
ret i1 %overflow
|
||||||
|
; Was returning false, should return true (not constant folded yet though).
|
||||||
|
; PR13991
|
||||||
|
; CHECK: test5:
|
||||||
|
; CHECK-NOT: xorb
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue