mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-07 11:33:44 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222072 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e7873018b5
commit
57b2b0c4da
@ -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
Block a user