forked from OSchip/llvm-project
R600: Factor i64 UDIVREM lowering into its own fuction
This is so it could potentially be used by SI. However, the current implementation does not always produce correct results, so the IntegerDivisionPass is being used instead. llvm-svn: 222072
This commit is contained in:
parent
2f68dadb0a
commit
bf69d76106
|
@ -1562,11 +1562,92 @@ SDValue AMDGPUTargetLowering::LowerDIVREM24(SDValue Op, SelectionDAG &DAG, bool
|
|||
return DAG.getMergeValues(Res, DL);
|
||||
}
|
||||
|
||||
void AMDGPUTargetLowering::LowerUDIVREM64(SDValue Op,
|
||||
SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &Results) const {
|
||||
assert(Op.getValueType() == MVT::i64);
|
||||
|
||||
SDLoc DL(Op);
|
||||
EVT VT = Op.getValueType();
|
||||
EVT HalfVT = VT.getHalfSizedIntegerVT(*DAG.getContext());
|
||||
|
||||
SDValue one = DAG.getConstant(1, HalfVT);
|
||||
SDValue zero = DAG.getConstant(0, HalfVT);
|
||||
|
||||
//HiLo split
|
||||
SDValue LHS = Op.getOperand(0);
|
||||
SDValue LHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, LHS, zero);
|
||||
SDValue LHS_Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, LHS, one);
|
||||
|
||||
SDValue RHS = Op.getOperand(1);
|
||||
SDValue RHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, RHS, zero);
|
||||
SDValue RHS_Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, RHS, one);
|
||||
|
||||
// Get Speculative values
|
||||
SDValue DIV_Part = DAG.getNode(ISD::UDIV, DL, HalfVT, LHS_Hi, RHS_Lo);
|
||||
SDValue REM_Part = DAG.getNode(ISD::UREM, DL, HalfVT, LHS_Hi, RHS_Lo);
|
||||
|
||||
SDValue REM_Hi = zero;
|
||||
SDValue REM_Lo = DAG.getSelectCC(DL, RHS_Hi, zero, REM_Part, LHS_Hi, ISD::SETEQ);
|
||||
|
||||
SDValue DIV_Hi = DAG.getSelectCC(DL, RHS_Hi, zero, DIV_Part, zero, ISD::SETEQ);
|
||||
SDValue DIV_Lo = zero;
|
||||
|
||||
const unsigned halfBitWidth = HalfVT.getSizeInBits();
|
||||
|
||||
for (unsigned i = 0; i < halfBitWidth; ++i) {
|
||||
SDValue POS = DAG.getConstant(halfBitWidth - i - 1, HalfVT);
|
||||
// Get Value of high bit
|
||||
SDValue HBit;
|
||||
if (halfBitWidth == 32 && Subtarget->hasBFE()) {
|
||||
HBit = DAG.getNode(AMDGPUISD::BFE_U32, DL, HalfVT, LHS_Lo, POS, one);
|
||||
} else {
|
||||
HBit = DAG.getNode(ISD::SRL, DL, HalfVT, LHS_Lo, POS);
|
||||
HBit = DAG.getNode(ISD::AND, DL, HalfVT, HBit, one);
|
||||
}
|
||||
|
||||
SDValue Carry = DAG.getNode(ISD::SRL, DL, HalfVT, REM_Lo,
|
||||
DAG.getConstant(halfBitWidth - 1, HalfVT));
|
||||
REM_Hi = DAG.getNode(ISD::SHL, DL, HalfVT, REM_Hi, one);
|
||||
REM_Hi = DAG.getNode(ISD::OR, DL, HalfVT, REM_Hi, Carry);
|
||||
|
||||
REM_Lo = DAG.getNode(ISD::SHL, DL, HalfVT, REM_Lo, one);
|
||||
REM_Lo = DAG.getNode(ISD::OR, DL, HalfVT, REM_Lo, HBit);
|
||||
|
||||
|
||||
SDValue REM = DAG.getNode(ISD::BUILD_PAIR, DL, VT, REM_Lo, REM_Hi);
|
||||
|
||||
SDValue BIT = DAG.getConstant(1 << (halfBitWidth - i - 1), HalfVT);
|
||||
SDValue realBIT = DAG.getSelectCC(DL, REM, RHS, BIT, zero, ISD::SETGE);
|
||||
|
||||
DIV_Lo = DAG.getNode(ISD::OR, DL, HalfVT, DIV_Lo, realBIT);
|
||||
|
||||
// Update REM
|
||||
|
||||
SDValue REM_sub = DAG.getNode(ISD::SUB, DL, VT, REM, RHS);
|
||||
|
||||
REM = DAG.getSelectCC(DL, REM, RHS, REM_sub, REM, ISD::SETGE);
|
||||
REM_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, REM, zero);
|
||||
REM_Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, REM, one);
|
||||
}
|
||||
|
||||
SDValue REM = DAG.getNode(ISD::BUILD_PAIR, DL, VT, REM_Lo, REM_Hi);
|
||||
SDValue DIV = DAG.getNode(ISD::BUILD_PAIR, DL, VT, DIV_Lo, DIV_Hi);
|
||||
Results.push_back(DIV);
|
||||
Results.push_back(REM);
|
||||
}
|
||||
|
||||
SDValue AMDGPUTargetLowering::LowerUDIVREM(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
SDLoc DL(Op);
|
||||
EVT VT = Op.getValueType();
|
||||
|
||||
if (VT == MVT::i64) {
|
||||
SmallVector<SDValue, 2> Results;
|
||||
LowerUDIVREM64(Op, DAG, Results);
|
||||
return DAG.getMergeValues(Results, DL);
|
||||
}
|
||||
|
||||
SDValue Num = Op.getOperand(0);
|
||||
SDValue Den = Op.getOperand(1);
|
||||
|
||||
|
|
|
@ -87,6 +87,8 @@ protected:
|
|||
SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerSDIVREM(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerDIVREM24(SDValue Op, SelectionDAG &DAG, bool sign) const;
|
||||
void LowerUDIVREM64(SDValue Op, SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &Results) const;
|
||||
bool isHWTrueValue(SDValue Op) const;
|
||||
bool isHWFalseValue(SDValue Op) const;
|
||||
|
||||
|
|
|
@ -907,74 +907,7 @@ void R600TargetLowering::ReplaceNodeResults(SDNode *N,
|
|||
}
|
||||
case ISD::UDIVREM: {
|
||||
SDValue Op = SDValue(N, 0);
|
||||
SDLoc DL(Op);
|
||||
EVT VT = Op.getValueType();
|
||||
EVT HalfVT = VT.getHalfSizedIntegerVT(*DAG.getContext());
|
||||
|
||||
SDValue one = DAG.getConstant(1, HalfVT);
|
||||
SDValue zero = DAG.getConstant(0, HalfVT);
|
||||
|
||||
//HiLo split
|
||||
SDValue LHS = N->getOperand(0);
|
||||
SDValue LHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, LHS, zero);
|
||||
SDValue LHS_Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, LHS, one);
|
||||
|
||||
SDValue RHS = N->getOperand(1);
|
||||
SDValue RHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, RHS, zero);
|
||||
SDValue RHS_Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, RHS, one);
|
||||
|
||||
// Get Speculative values
|
||||
SDValue DIV_Part = DAG.getNode(ISD::UDIV, DL, HalfVT, LHS_Hi, RHS_Lo);
|
||||
SDValue REM_Part = DAG.getNode(ISD::UREM, DL, HalfVT, LHS_Hi, RHS_Lo);
|
||||
|
||||
SDValue REM_Hi = zero;
|
||||
SDValue REM_Lo = DAG.getSelectCC(DL, RHS_Hi, zero, REM_Part, LHS_Hi, ISD::SETEQ);
|
||||
|
||||
SDValue DIV_Hi = DAG.getSelectCC(DL, RHS_Hi, zero, DIV_Part, zero, ISD::SETEQ);
|
||||
SDValue DIV_Lo = zero;
|
||||
|
||||
const unsigned halfBitWidth = HalfVT.getSizeInBits();
|
||||
|
||||
for (unsigned i = 0; i < halfBitWidth; ++i) {
|
||||
SDValue POS = DAG.getConstant(halfBitWidth - i - 1, HalfVT);
|
||||
// Get Value of high bit
|
||||
SDValue HBit;
|
||||
if (halfBitWidth == 32 && Subtarget->hasBFE()) {
|
||||
HBit = DAG.getNode(AMDGPUISD::BFE_U32, DL, HalfVT, LHS_Lo, POS, one);
|
||||
} else {
|
||||
HBit = DAG.getNode(ISD::SRL, DL, HalfVT, LHS_Lo, POS);
|
||||
HBit = DAG.getNode(ISD::AND, DL, HalfVT, HBit, one);
|
||||
}
|
||||
|
||||
SDValue Carry = DAG.getNode(ISD::SRL, DL, HalfVT, REM_Lo,
|
||||
DAG.getConstant(halfBitWidth - 1, HalfVT));
|
||||
REM_Hi = DAG.getNode(ISD::SHL, DL, HalfVT, REM_Hi, one);
|
||||
REM_Hi = DAG.getNode(ISD::OR, DL, HalfVT, REM_Hi, Carry);
|
||||
|
||||
REM_Lo = DAG.getNode(ISD::SHL, DL, HalfVT, REM_Lo, one);
|
||||
REM_Lo = DAG.getNode(ISD::OR, DL, HalfVT, REM_Lo, HBit);
|
||||
|
||||
|
||||
SDValue REM = DAG.getNode(ISD::BUILD_PAIR, DL, VT, REM_Lo, REM_Hi);
|
||||
|
||||
SDValue BIT = DAG.getConstant(1 << (halfBitWidth - i - 1), HalfVT);
|
||||
SDValue realBIT = DAG.getSelectCC(DL, REM, RHS, BIT, zero, ISD::SETGE);
|
||||
|
||||
DIV_Lo = DAG.getNode(ISD::OR, DL, HalfVT, DIV_Lo, realBIT);
|
||||
|
||||
// Update REM
|
||||
|
||||
SDValue REM_sub = DAG.getNode(ISD::SUB, DL, VT, REM, RHS);
|
||||
|
||||
REM = DAG.getSelectCC(DL, REM, RHS, REM_sub, REM, ISD::SETGE);
|
||||
REM_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, REM, zero);
|
||||
REM_Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, REM, one);
|
||||
}
|
||||
|
||||
SDValue REM = DAG.getNode(ISD::BUILD_PAIR, DL, VT, REM_Lo, REM_Hi);
|
||||
SDValue DIV = DAG.getNode(ISD::BUILD_PAIR, DL, VT, DIV_Lo, DIV_Hi);
|
||||
Results.push_back(DIV);
|
||||
Results.push_back(REM);
|
||||
LowerUDIVREM64(Op, DAG, Results);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue