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 | 0b3ca50ebb26ea246a540a8123d81a97ab78ccbd (patch) | |
tree | ca2812a7a7f79c00a6f9aa178b434c74d1ec4baf | |
parent | 7da1166da010a2ea4156e83bd2efac5fb73b719b (diff) | |
download | bcm5719-llvm-0b3ca50ebb26ea246a540a8123d81a97ab78ccbd.tar.gz bcm5719-llvm-0b3ca50ebb26ea246a540a8123d81a97ab78ccbd.zip |
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.
llvm-svn: 122221
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index abd21a35c73..b9e55992cca 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/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 //===----------------------------------------------------------------------===// |