[PATCH v2 1/3] R600: Implement custom SDIVREM.

Matt Arsenault arsenm2 at gmail.com
Sun Jun 22 14:21:31 PDT 2014


On Jun 22, 2014, at 12:58 PM, Jan Vesely <jan.vesely at rutgers.edu> wrote:

> Instead of separate SDIV/SREM. SDIV used UDIV which in turn used UDIVREM anyway.
> SREM used SDIV(UDIV->UDIVREM)+MUL+SUB, using UDIVREM directly is more efficient.
> 
> v2: Don't use all caps names
> 
> Signed-off-by: Jan Vesely <jan.vesely at rutgers.edu>
> ---
> lib/Target/R600/AMDGPUISelLowering.cpp | 47 +++++++++++++++++++++++++++++++---
> lib/Target/R600/AMDGPUISelLowering.h   |  1 +
> 2 files changed, 44 insertions(+), 4 deletions(-)

LGTM

> 
> diff --git a/lib/Target/R600/AMDGPUISelLowering.cpp b/lib/Target/R600/AMDGPUISelLowering.cpp
> index d7ae5e8..caf701b 100644
> --- a/lib/Target/R600/AMDGPUISelLowering.cpp
> +++ b/lib/Target/R600/AMDGPUISelLowering.cpp
> @@ -234,10 +234,10 @@ AMDGPUTargetLowering::AMDGPUTargetLowering(TargetMachine &TM) :
>   const MVT ScalarIntVTs[] = { MVT::i32, MVT::i64 };
>   for (MVT VT : ScalarIntVTs) {
>     setOperationAction(ISD::SREM, VT, Expand);
> -    setOperationAction(ISD::SDIV, VT, Custom);
> +    setOperationAction(ISD::SDIV, VT, Expand);
> 
>     // GPU does not have divrem function for signed or unsigned.
> -    setOperationAction(ISD::SDIVREM, VT, Expand);
> +    setOperationAction(ISD::SDIVREM, VT, Custom);
>     setOperationAction(ISD::UDIVREM, VT, Custom);
> 
>     // GPU does not have [S|U]MUL_LOHI functions as a single instruction.
> @@ -297,13 +297,13 @@ AMDGPUTargetLowering::AMDGPUTargetLowering(TargetMachine &TM) :
>     setOperationAction(ISD::SINT_TO_FP, VT, Expand);
>     setOperationAction(ISD::UINT_TO_FP, VT, Expand);
>     // TODO: Implement custom UREM / SREM routines.
> -    setOperationAction(ISD::SDIV, VT, Custom);
> +    setOperationAction(ISD::SDIV, VT, Expand);
>     setOperationAction(ISD::UDIV, VT, Expand);
>     setOperationAction(ISD::SREM, VT, Expand);
>     setOperationAction(ISD::UREM, VT, Expand);
>     setOperationAction(ISD::SMUL_LOHI, VT, Expand);
>     setOperationAction(ISD::UMUL_LOHI, VT, Expand);
> -    setOperationAction(ISD::SDIVREM, VT, Expand);
> +    setOperationAction(ISD::SDIVREM, VT, Custom);
>     setOperationAction(ISD::UDIVREM, VT, Custom);
>     setOperationAction(ISD::SELECT, VT, Expand);
>     setOperationAction(ISD::VSELECT, VT, Expand);
> @@ -510,6 +510,7 @@ SDValue AMDGPUTargetLowering::LowerOperation(SDValue Op,
>   case ISD::SDIV: return LowerSDIV(Op, DAG);
>   case ISD::SREM: return LowerSREM(Op, DAG);
>   case ISD::UDIVREM: return LowerUDIVREM(Op, DAG);
> +  case ISD::SDIVREM: return LowerSDIVREM(Op, DAG);
>   case ISD::FCEIL: return LowerFCEIL(Op, DAG);
>   case ISD::FTRUNC: return LowerFTRUNC(Op, DAG);
>   case ISD::FRINT: return LowerFRINT(Op, DAG);
> @@ -1618,6 +1619,44 @@ SDValue AMDGPUTargetLowering::LowerUDIVREM(SDValue Op,
>   return DAG.getMergeValues(Ops, DL);
> }
> 
> +SDValue AMDGPUTargetLowering::LowerSDIVREM(SDValue Op,
> +                                           SelectionDAG &DAG) const {
> +  SDLoc DL(Op);
> +  EVT VT = Op.getValueType();
> +
> +  SDValue Zero = DAG.getConstant(0, VT);
> +  SDValue NegOne = DAG.getConstant(-1, VT);
> +
> +  SDValue LHS = Op.getOperand(0);
> +  SDValue RHS = Op.getOperand(1);
> +
> +  SDValue LHSign = DAG.getSelectCC(DL, LHS, Zero, NegOne, Zero, ISD::SETLT);
> +  SDValue RHSign = DAG.getSelectCC(DL, RHS, Zero, NegOne, Zero, ISD::SETLT);
> +  SDValue DSign = DAG.getNode(ISD::XOR, DL, VT, LHSign, RHSign);
> +  SDValue RSign = LHSign; // Remainder sign is the same as LHS
> +
> +  LHS = DAG.getNode(ISD::ADD, DL, VT, LHS, LHSign);
> +  RHS = DAG.getNode(ISD::ADD, DL, VT, RHS, RHSign);
> +
> +  LHS = DAG.getNode(ISD::XOR, DL, VT, LHS, LHSign);
> +  RHS = DAG.getNode(ISD::XOR, DL, VT, RHS, RHSign);
> +
> +  SDValue Div = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(VT, VT), LHS, RHS);
> +  SDValue Rem = Div.getValue(1);
> +
> +  Div = DAG.getNode(ISD::XOR, DL, VT, Div, DSign);
> +  Rem = DAG.getNode(ISD::XOR, DL, VT, Rem, RSign);
> +
> +  Div = DAG.getNode(ISD::SUB, DL, VT, Div, DSign);
> +  Rem = DAG.getNode(ISD::SUB, DL, VT, Rem, RSign);
> +
> +  SDValue Res[2] = {
> +    Div,
> +    Rem
> +  };
> +  return DAG.getMergeValues(Res, DL);
> +}
> +
> SDValue AMDGPUTargetLowering::LowerFCEIL(SDValue Op, SelectionDAG &DAG) const {
>   SDLoc SL(Op);
>   SDValue Src = Op.getOperand(0);
> diff --git a/lib/Target/R600/AMDGPUISelLowering.h b/lib/Target/R600/AMDGPUISelLowering.h
> index e2000a0..0db89ecb 100644
> --- a/lib/Target/R600/AMDGPUISelLowering.h
> +++ b/lib/Target/R600/AMDGPUISelLowering.h
> @@ -50,6 +50,7 @@ private:
>   SDValue LowerSREM(SDValue Op, SelectionDAG &DAG) const;
>   SDValue LowerSREM32(SDValue Op, SelectionDAG &DAG) const;
>   SDValue LowerSREM64(SDValue Op, SelectionDAG &DAG) const;
> +  SDValue LowerSDIVREM(SDValue Op, SelectionDAG &DAG) const;
>   SDValue LowerUDIVREM(SDValue Op, SelectionDAG &DAG) const;
>   SDValue LowerFCEIL(SDValue Op, SelectionDAG &DAG) const;
>   SDValue LowerFTRUNC(SDValue Op, SelectionDAG &DAG) const;
> -- 
> 1.9.3
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits





More information about the llvm-commits mailing list