Fix wrong logic in promotion of signed mul-with-overflow (I pointed this out at

the time but presumably my email got lost).  Examples where the previous logic
got it wrong: (1) a signed i8 multiply of 64 by 2 overflows, but the high part is
zero; (2) a signed i8 multiple of -128 by 2 overflows, but the high part is all
ones. 


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125748 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan Sands 2011-02-17 12:42:48 +00:00
parent 6904f05e60
commit fbd53f79f5

View File

@ -548,16 +548,15 @@ SDValue DAGTypeLegalizer::PromoteIntRes_UADDSUBO(SDNode *N, unsigned ResNo) {
return Res;
}
SDValue DAGTypeLegalizer::PromoteIntRes_XMULO(SDNode *N, unsigned ResNo) {
// Promote the overflow bit trivially.
if (ResNo == 1)
return PromoteIntRes_Overflow(N);
SDValue LHS = N->getOperand(0), RHS = N->getOperand(1);
DebugLoc DL = N->getDebugLoc();
unsigned SmallSize = LHS.getValueType().getSizeInBits();
EVT SmallVT = LHS.getValueType();
// 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 the result
// to see if the overflow happened.
@ -568,26 +567,22 @@ SDValue DAGTypeLegalizer::PromoteIntRes_XMULO(SDNode *N, unsigned ResNo) {
LHS = ZExtPromotedInteger(LHS);
RHS = ZExtPromotedInteger(RHS);
}
SDValue Mul = DAG.getNode(ISD::MUL, DL, LHS.getValueType(), LHS, RHS);
// For an unsigned overflow, we check to see if the high part is != 0;
// Overflow occurred iff the high part of the result does not zero/sign-extend
// the low part.
SDValue Overflow;
if (N->getOpcode() == ISD::UMULO) {
// Unsigned overflow occurred iff the high part is non-zero.
SDValue Hi = DAG.getNode(ISD::SRL, DL, Mul.getValueType(), Mul,
DAG.getIntPtrConstant(SmallSize));
// Overflowed if and only if this is not equal to Res.
DAG.getIntPtrConstant(SmallVT.getSizeInBits()));
Overflow = DAG.getSetCC(DL, N->getValueType(1), Hi,
DAG.getConstant(0, Hi.getValueType()), ISD::SETNE);
} else {
// Signed multiply overflowed if the high part is not 0 and not -1.
SDValue Hi = DAG.getNode(ISD::SRA, DL, Mul.getValueType(), Mul,
DAG.getIntPtrConstant(SmallSize));
Hi = DAG.getNode(ISD::ADD, DL, Hi.getValueType(), Hi,
DAG.getConstant(1, Hi.getValueType()));
Overflow = DAG.getSetCC(DL, N->getValueType(1), Hi,
DAG.getConstant(1, Hi.getValueType()), ISD::SETUGT);
// Signed overflow occurred iff the high part does not sign extend the low.
SDValue SExt = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, Mul.getValueType(),
Mul, DAG.getValueType(SmallVT));
Overflow = DAG.getSetCC(DL, N->getValueType(1), SExt, Mul, ISD::SETNE);
}
// Use the calculated overflow everywhere.
@ -595,7 +590,6 @@ SDValue DAGTypeLegalizer::PromoteIntRes_XMULO(SDNode *N, unsigned ResNo) {
return Mul;
}
SDValue DAGTypeLegalizer::PromoteIntRes_UDIV(SDNode *N) {
// Zero extend the input.
SDValue LHS = ZExtPromotedInteger(N->getOperand(0));