diff options
author | Chris Lattner <sabre@nondot.org> | 2010-12-20 02:05:39 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-12-20 02:05:39 +0000 |
commit | 5c3d4f0fc90c86a6c4ee9871835d70c9ff3833d5 (patch) | |
tree | 3049083b4409c2ee3289df69797196c46b2c2c2b /lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | |
parent | 23a0199f05fe61c4bde921d5729ed2b927657bcb (diff) |
implement type legalization promotion support for SMULO and UMULO, giving
ARM (and other 32-bit-only) targets support for i8 and i16 overflow
multiplies. The generated code isn't great, but this at least fixes
CodeGen/Generic/overflow.ll when running on ARM hosts.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122221 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index abd21a35c7..b9e55992cc 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -548,6 +548,54 @@ 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(); + + // 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. + if (N->getOpcode() == ISD::SMULO) { + LHS = SExtPromotedInteger(LHS); + RHS = SExtPromotedInteger(RHS); + } else { + 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; + SDValue Overflow; + if (N->getOpcode() == ISD::UMULO) { + SDValue Hi = DAG.getNode(ISD::SRL, DL, Mul.getValueType(), Mul, + DAG.getIntPtrConstant(SmallSize)); + // Overflowed if and only if this is not equal to Res. + 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); + } + + // Use the calculated overflow everywhere. + ReplaceValueWith(SDValue(N, 1), Overflow); + return Mul; +} + + SDValue DAGTypeLegalizer::PromoteIntRes_UDIV(SDNode *N) { // Zero extend the input. SDValue LHS = ZExtPromotedInteger(N->getOperand(0)); @@ -601,11 +649,6 @@ SDValue DAGTypeLegalizer::PromoteIntRes_VAARG(SDNode *N) { return Res; } -SDValue DAGTypeLegalizer::PromoteIntRes_XMULO(SDNode *N, unsigned ResNo) { - assert(ResNo == 1 && "Only boolean result promotion currently supported!"); - return PromoteIntRes_Overflow(N); -} - //===----------------------------------------------------------------------===// // Integer Operand Promotion //===----------------------------------------------------------------------===// |