[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