[PATCH RFC 3/4] R600: Implement iterative algorithm for udivrem

Tom Stellard tom at stellard.net
Fri Apr 25 12:23:06 PDT 2014


On Fri, Apr 25, 2014 at 03:08:37PM -0400, Jan Vesely wrote:
> Initial implementation, rather slow
> 

Can you add tests for i64 div, just to make sure the compiler doesn't
crash.  You don't need to check all the generated instructions, just
S_ENDPGM.

-Tom

> Signed-off-by: Jan Vesely <jan.vesely at rutgers.edu>
> ---
>  lib/Target/R600/AMDGPUISelLowering.cpp | 50 ++++++++++++++++++++++++++++++++++
>  1 file changed, 50 insertions(+)
> 
> diff --git a/lib/Target/R600/AMDGPUISelLowering.cpp b/lib/Target/R600/AMDGPUISelLowering.cpp
> index 01d1eaf..a004b91 100644
> --- a/lib/Target/R600/AMDGPUISelLowering.cpp
> +++ b/lib/Target/R600/AMDGPUISelLowering.cpp
> @@ -429,6 +429,56 @@ void AMDGPUTargetLowering::ReplaceNodeResults(SDNode *N,
>      Results.push_back(UDIVREM.getValue(1));
>      break;
>    }
> +  case ISD::UDIVREM: {
> +    SDValue Op = SDValue(N, 0);
> +    SDLoc DL(Op);
> +    EVT VT = Op.getValueType();
> +    EVT HalfVT = VT.getHalfSizedIntegerVT(*DAG.getContext());
> +
> +    //HiLo split
> +    SDValue LHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT,
> +      N->getOperand(0), DAG.getConstant(0, HalfVT));
> +    SDValue LHS_Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT,
> +      N->getOperand(0), DAG.getConstant(1, HalfVT));
> +
> +    SDValue RHS = N->getOperand(1);
> +
> +    SDValue DIV = DAG.getConstant(0, VT);
> +    SDValue REM = DAG.getConstant(0, VT);
> +
> +    const unsigned bitWidth = VT.getSizeInBits();
> +    const unsigned halfBitWidth = HalfVT.getSizeInBits();
> +
> +    SDValue one = DAG.getConstant(1, HalfVT);
> +    SDValue one_VT = DAG.getConstant(1, VT);
> +    for (unsigned i = 0; i < bitWidth; ++i) {
> +      SDValue POS = DAG.getConstant((bitWidth - i - 1) % halfBitWidth, HalfVT);
> +      // Get Value of high bit
> +      SDValue HBit = DAG.getNode(ISD::SRL, DL, HalfVT,
> +        i < halfBitWidth ? LHS_Hi : LHS_Lo, POS);
> +      HBit = DAG.getNode(ISD::AND, DL, HalfVT, HBit, one);
> +      HBit = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, HBit);
> +
> +      // Add the high bit to shifted remainder
> +      REM = DAG.getNode(ISD::SHL, DL, VT, REM, one);
> +      REM = DAG.getNode(ISD::OR, DL, VT, REM, HBit);
> +
> +      // Update DIV
> +      SDValue ShDIV = DAG.getNode(ISD::SHL, DL, VT, DIV, one);
> +      SDValue ShDIV_plus = DAG.getNode(ISD::OR, DL, VT, ShDIV, one_VT);
> +
> +      DIV = DAG.getSelectCC(DL, REM, RHS, ShDIV_plus, ShDIV, ISD::SETGE);
> +
> +      // Update REM
> +      SDValue REM_sub = DAG.getNode(ISD::SUB, DL, VT, REM, RHS);
> +
> +      REM = DAG.getSelectCC(DL, REM, RHS, REM_sub, REM, ISD::SETGE);
> +    }
> +
> +    Results.push_back(DIV);
> +    Results.push_back(REM);
> +    break;
> +  }
>    default:
>      return;
>    }
> -- 
> 1.9.0
> 



More information about the llvm-commits mailing list