mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
R600: Use LowerSDIVREM for i64 node replace
v2: move div/rem node replacement to R600ISelLowering make lowerSDIVREM protected Signed-off-by: Jan Vesely <jan.vesely@rutgers.edu> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211478 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -530,96 +530,6 @@ void AMDGPUTargetLowering::ReplaceNodeResults(SDNode *N,
|
||||
// ReplaceNodeResults to sext_in_reg to an illegal type, so we'll just do
|
||||
// nothing here and let the illegal result integer be handled normally.
|
||||
return;
|
||||
case ISD::UDIV: {
|
||||
SDValue Op = SDValue(N, 0);
|
||||
SDLoc DL(Op);
|
||||
EVT VT = Op.getValueType();
|
||||
SDValue UDIVREM = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(VT, VT),
|
||||
N->getOperand(0), N->getOperand(1));
|
||||
Results.push_back(UDIVREM);
|
||||
break;
|
||||
}
|
||||
case ISD::UREM: {
|
||||
SDValue Op = SDValue(N, 0);
|
||||
SDLoc DL(Op);
|
||||
EVT VT = Op.getValueType();
|
||||
SDValue UDIVREM = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(VT, VT),
|
||||
N->getOperand(0), N->getOperand(1));
|
||||
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());
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@@ -50,7 +50,6 @@ 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;
|
||||
@@ -83,6 +82,7 @@ protected:
|
||||
SDValue SplitVectorStore(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerSDIVREM(SDValue Op, SelectionDAG &DAG) const;
|
||||
bool isHWTrueValue(SDValue Op) const;
|
||||
bool isHWFalseValue(SDValue Op) const;
|
||||
|
||||
|
@@ -156,6 +156,8 @@ R600TargetLowering::R600TargetLowering(TargetMachine &TM) :
|
||||
// during Type Legalization
|
||||
setOperationAction(ISD::UDIV, MVT::i64, Custom);
|
||||
setOperationAction(ISD::UREM, MVT::i64, Custom);
|
||||
setOperationAction(ISD::SDIV, MVT::i64, Custom);
|
||||
setOperationAction(ISD::SREM, MVT::i64, Custom);
|
||||
|
||||
// We don't have 64-bit shifts. Thus we need either SHX i64 or SHX_PARTS i32
|
||||
// to be Legal/Custom in order to avoid library calls.
|
||||
@@ -826,11 +828,127 @@ void R600TargetLowering::ReplaceNodeResults(SDNode *N,
|
||||
DAG.ReplaceAllUsesOfValueWith(SDValue(N,1), SDValue(Node, 1));
|
||||
return;
|
||||
}
|
||||
case ISD::STORE:
|
||||
case ISD::STORE: {
|
||||
SDNode *Node = LowerSTORE(SDValue(N, 0), DAG).getNode();
|
||||
Results.push_back(SDValue(Node, 0));
|
||||
return;
|
||||
}
|
||||
case ISD::UDIV: {
|
||||
SDValue Op = SDValue(N, 0);
|
||||
SDLoc DL(Op);
|
||||
EVT VT = Op.getValueType();
|
||||
SDValue UDIVREM = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(VT, VT),
|
||||
N->getOperand(0), N->getOperand(1));
|
||||
Results.push_back(UDIVREM);
|
||||
break;
|
||||
}
|
||||
case ISD::UREM: {
|
||||
SDValue Op = SDValue(N, 0);
|
||||
SDLoc DL(Op);
|
||||
EVT VT = Op.getValueType();
|
||||
SDValue UDIVREM = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(VT, VT),
|
||||
N->getOperand(0), N->getOperand(1));
|
||||
Results.push_back(UDIVREM.getValue(1));
|
||||
break;
|
||||
}
|
||||
case ISD::SDIV: {
|
||||
SDValue Op = SDValue(N, 0);
|
||||
SDLoc DL(Op);
|
||||
EVT VT = Op.getValueType();
|
||||
SDValue SDIVREM = DAG.getNode(ISD::SDIVREM, DL, DAG.getVTList(VT, VT),
|
||||
N->getOperand(0), N->getOperand(1));
|
||||
Results.push_back(SDIVREM);
|
||||
break;
|
||||
}
|
||||
case ISD::SREM: {
|
||||
SDValue Op = SDValue(N, 0);
|
||||
SDLoc DL(Op);
|
||||
EVT VT = Op.getValueType();
|
||||
SDValue SDIVREM = DAG.getNode(ISD::SDIVREM, DL, DAG.getVTList(VT, VT),
|
||||
N->getOperand(0), N->getOperand(1));
|
||||
Results.push_back(SDIVREM.getValue(1));
|
||||
break;
|
||||
}
|
||||
case ISD::SDIVREM: {
|
||||
SDValue Op = SDValue(N, 1);
|
||||
SDValue RES = LowerSDIVREM(Op, DAG);
|
||||
Results.push_back(RES);
|
||||
Results.push_back(RES.getValue(1));
|
||||
break;
|
||||
}
|
||||
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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDValue R600TargetLowering::vectorToVerticalVector(SelectionDAG &DAG,
|
||||
|
Reference in New Issue
Block a user