diff options
author | Duncan Sands <baldrick@free.fr> | 2011-02-17 12:42:48 +0000 |
---|---|---|
committer | Duncan Sands <baldrick@free.fr> | 2011-02-17 12:42:48 +0000 |
commit | c6196aa48183a6cada8458c45fbc9f5e31b08e8d (patch) | |
tree | 0c7d2d0a8da7fb8e032892d4bfd8e3d9924fbb0f /llvm/lib/CodeGen | |
parent | 4c14a5cc2cdf7ca9347110f7534cd50d1c9f7e6e (diff) | |
download | bcm5719-llvm-c6196aa48183a6cada8458c45fbc9f5e31b08e8d.tar.gz bcm5719-llvm-c6196aa48183a6cada8458c45fbc9f5e31b08e8d.zip |
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.
llvm-svn: 125748
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 30 |
1 files changed, 12 insertions, 18 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 7f860e4d055..f0752df80f1 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -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)); |