diff options
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonISelLowering.cpp')
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelLowering.cpp | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp index b72498777ed..fef5a98cdb0 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -1334,8 +1334,8 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM, // Hexagon has A4_addp_c and A4_subp_c that take and generate a carry bit, // but they only operate on i64. for (MVT VT : MVT::integer_valuetypes()) { - setOperationAction(ISD::UADDO, VT, Expand); - setOperationAction(ISD::USUBO, VT, Expand); + setOperationAction(ISD::UADDO, VT, Custom); + setOperationAction(ISD::USUBO, VT, Custom); setOperationAction(ISD::SADDO, VT, Expand); setOperationAction(ISD::SSUBO, VT, Expand); setOperationAction(ISD::ADDCARRY, VT, Expand); @@ -2692,6 +2692,43 @@ HexagonTargetLowering::LowerUnalignedLoad(SDValue Op, SelectionDAG &DAG) } SDValue +HexagonTargetLowering::LowerUAddSubO(SDValue Op, SelectionDAG &DAG) const { + SDValue X = Op.getOperand(0), Y = Op.getOperand(1); + auto *CY = dyn_cast<ConstantSDNode>(Y); + if (!CY) + return SDValue(); + + const SDLoc &dl(Op); + SDVTList VTs = Op.getNode()->getVTList(); + assert(VTs.NumVTs == 2); + assert(VTs.VTs[1] == MVT::i1); + unsigned Opc = Op.getOpcode(); + + if (CY) { + uint32_t VY = CY->getZExtValue(); + assert(VY != 0 && "This should have been folded"); + // X +/- 1 + if (VY != 1) + return SDValue(); + + if (Opc == ISD::UADDO) { + SDValue Op = DAG.getNode(ISD::ADD, dl, VTs.VTs[0], {X, Y}); + SDValue Ov = DAG.getSetCC(dl, MVT::i1, Op, getZero(dl, ty(Op), DAG), + ISD::SETEQ); + return DAG.getMergeValues({Op, Ov}, dl); + } + if (Opc == ISD::USUBO) { + SDValue Op = DAG.getNode(ISD::SUB, dl, VTs.VTs[0], {X, Y}); + SDValue Ov = DAG.getSetCC(dl, MVT::i1, Op, + DAG.getConstant(-1, dl, ty(Op)), ISD::SETEQ); + return DAG.getMergeValues({Op, Ov}, dl); + } + } + + return SDValue(); +} + +SDValue HexagonTargetLowering::LowerAddSubCarry(SDValue Op, SelectionDAG &DAG) const { const SDLoc &dl(Op); unsigned Opc = Op.getOpcode(); @@ -2768,6 +2805,8 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::BITCAST: return LowerBITCAST(Op, DAG); case ISD::LOAD: return LowerLoad(Op, DAG); case ISD::STORE: return LowerStore(Op, DAG); + case ISD::UADDO: + case ISD::USUBO: return LowerUAddSubO(Op, DAG); case ISD::ADDCARRY: case ISD::SUBCARRY: return LowerAddSubCarry(Op, DAG); case ISD::SRA: |