SelectionDAG: Factor ISD::MUL lowering code out of DAGTypeLegalizer

This code has been moved to a new function in the TargetLowering
class called expandMUL().  The purpose of this is to be able
to share lowering code between the SelectionDAGLegalize and
DAGTypeLegalizer classes.

No functionality changed intended.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206036 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Tom Stellard 2014-04-11 16:11:58 +00:00
parent ae6f7070ba
commit fdde7d2110
3 changed files with 130 additions and 66 deletions

View File

@ -2375,6 +2375,24 @@ public:
SDValue BuildUDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization,
std::vector<SDNode*> *Created) const;
//===--------------------------------------------------------------------===//
// Legalization utility functions
//
/// Expand a MUL into two nodes. One that computes the high bits of
/// the result and one that computes the low bits.
/// \param VT The value type to use for the Lo and Hi nodes.
/// \param LL Low bits of the LHS of the MUL. You can use this parameter
/// if you want to control how low bits are extracted from the LHS.
/// \param LH High bits of the LHS of the MUL. See LL for meaning.
/// \param RL Low bits of the RHS of the MUL. See LL for meaning
/// \param RH High bits of the RHS of the MUL. See LL for meaning.
/// \returns true if the node has been expanded. false if it has not
bool expandMUL(SDNode *N, SDValue &Lo, SDValue &Hi, EVT HiLoVT,
SelectionDAG &DAG, SDValue LL = SDValue(),
SDValue LH = SDValue(), SDValue RL = SDValue(),
SDValue RH = SDValue()) const;
//===--------------------------------------------------------------------===//
// Instruction Emitting Hooks
//

View File

@ -1923,73 +1923,12 @@ void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N,
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
SDLoc dl(N);
bool HasMULHS = TLI.isOperationLegalOrCustom(ISD::MULHS, NVT);
bool HasMULHU = TLI.isOperationLegalOrCustom(ISD::MULHU, NVT);
bool HasSMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::SMUL_LOHI, NVT);
bool HasUMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::UMUL_LOHI, NVT);
if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) {
SDValue LL, LH, RL, RH;
GetExpandedInteger(N->getOperand(0), LL, LH);
GetExpandedInteger(N->getOperand(1), RL, RH);
unsigned OuterBitSize = VT.getSizeInBits();
unsigned InnerBitSize = NVT.getSizeInBits();
unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0));
unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1));
SDValue LL, LH, RL, RH;
GetExpandedInteger(N->getOperand(0), LL, LH);
GetExpandedInteger(N->getOperand(1), RL, RH);
APInt HighMask = APInt::getHighBitsSet(OuterBitSize, InnerBitSize);
if (DAG.MaskedValueIsZero(N->getOperand(0), HighMask) &&
DAG.MaskedValueIsZero(N->getOperand(1), HighMask)) {
// The inputs are both zero-extended.
if (HasUMUL_LOHI) {
// We can emit a umul_lohi.
Lo = DAG.getNode(ISD::UMUL_LOHI, dl, DAG.getVTList(NVT, NVT), LL, RL);
Hi = SDValue(Lo.getNode(), 1);
return;
}
if (HasMULHU) {
// We can emit a mulhu+mul.
Lo = DAG.getNode(ISD::MUL, dl, NVT, LL, RL);
Hi = DAG.getNode(ISD::MULHU, dl, NVT, LL, RL);
return;
}
}
if (LHSSB > InnerBitSize && RHSSB > InnerBitSize) {
// The input values are both sign-extended.
if (HasSMUL_LOHI) {
// We can emit a smul_lohi.
Lo = DAG.getNode(ISD::SMUL_LOHI, dl, DAG.getVTList(NVT, NVT), LL, RL);
Hi = SDValue(Lo.getNode(), 1);
return;
}
if (HasMULHS) {
// We can emit a mulhs+mul.
Lo = DAG.getNode(ISD::MUL, dl, NVT, LL, RL);
Hi = DAG.getNode(ISD::MULHS, dl, NVT, LL, RL);
return;
}
}
if (HasUMUL_LOHI) {
// Lo,Hi = umul LHS, RHS.
SDValue UMulLOHI = DAG.getNode(ISD::UMUL_LOHI, dl,
DAG.getVTList(NVT, NVT), LL, RL);
Lo = UMulLOHI;
Hi = UMulLOHI.getValue(1);
RH = DAG.getNode(ISD::MUL, dl, NVT, LL, RH);
LH = DAG.getNode(ISD::MUL, dl, NVT, LH, RL);
Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, RH);
Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, LH);
return;
}
if (HasMULHU) {
Lo = DAG.getNode(ISD::MUL, dl, NVT, LL, RL);
Hi = DAG.getNode(ISD::MULHU, dl, NVT, LL, RL);
RH = DAG.getNode(ISD::MUL, dl, NVT, LL, RH);
LH = DAG.getNode(ISD::MUL, dl, NVT, LH, RL);
Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, RH);
Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, LH);
return;
}
}
if (TLI.expandMUL(N, Lo, Hi, NVT, DAG, LL, LH, RL, RH))
return;
// If nothing else, we can make a libcall.
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;

View File

@ -2739,3 +2739,110 @@ verifyReturnAddressArgumentIsConstant(SDValue Op, SelectionDAG &DAG) const {
return false;
}
//===----------------------------------------------------------------------===//
// Legalization Utilities
//===----------------------------------------------------------------------===//
bool TargetLowering::expandMUL(SDNode *N, SDValue &Lo, SDValue &Hi, EVT HiLoVT,
SelectionDAG &DAG, SDValue LL, SDValue LH,
SDValue RL, SDValue RH) const {
EVT VT = N->getValueType(0);
SDLoc dl(N);
bool HasMULHS = isOperationLegalOrCustom(ISD::MULHS, HiLoVT);
bool HasMULHU = isOperationLegalOrCustom(ISD::MULHU, HiLoVT);
bool HasSMUL_LOHI = isOperationLegalOrCustom(ISD::SMUL_LOHI, HiLoVT);
bool HasUMUL_LOHI = isOperationLegalOrCustom(ISD::UMUL_LOHI, HiLoVT);
if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) {
unsigned OuterBitSize = VT.getSizeInBits();
unsigned InnerBitSize = HiLoVT.getSizeInBits();
unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0));
unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1));
// LL, LH, RL, and RH must be either all NULL or all set to a value.
assert((LL.getNode() && LH.getNode() && RL.getNode() && RH.getNode()) ||
(!LL.getNode() && !LH.getNode() && !RL.getNode() && !RH.getNode()));
if (!LL.getNode() && !RL.getNode() &&
isOperationLegalOrCustom(ISD::TRUNCATE, HiLoVT)) {
LL = DAG.getNode(ISD::TRUNCATE, dl, HiLoVT, N->getOperand(0));
RL = DAG.getNode(ISD::TRUNCATE, dl, HiLoVT, N->getOperand(1));
}
if (!LL.getNode())
return false;
APInt HighMask = APInt::getHighBitsSet(OuterBitSize, InnerBitSize);
if (DAG.MaskedValueIsZero(N->getOperand(0), HighMask) &&
DAG.MaskedValueIsZero(N->getOperand(1), HighMask)) {
// The inputs are both zero-extended.
if (HasUMUL_LOHI) {
// We can emit a umul_lohi.
Lo = DAG.getNode(ISD::UMUL_LOHI, dl,
DAG.getVTList(HiLoVT, HiLoVT), LL, RL);
Hi = SDValue(Lo.getNode(), 1);
return true;
}
if (HasMULHU) {
// We can emit a mulhu+mul.
Lo = DAG.getNode(ISD::MUL, dl, HiLoVT, LL, RL);
Hi = DAG.getNode(ISD::MULHU, dl, HiLoVT, LL, RL);
return true;
}
}
if (LHSSB > InnerBitSize && RHSSB > InnerBitSize) {
// The input values are both sign-extended.
if (HasSMUL_LOHI) {
// We can emit a smul_lohi.
Lo = DAG.getNode(ISD::SMUL_LOHI, dl,
DAG.getVTList(HiLoVT, HiLoVT), LL, RL);
Hi = SDValue(Lo.getNode(), 1);
return true;
}
if (HasMULHS) {
// We can emit a mulhs+mul.
Lo = DAG.getNode(ISD::MUL, dl, HiLoVT, LL, RL);
Hi = DAG.getNode(ISD::MULHS, dl, HiLoVT, LL, RL);
return true;
}
}
if (!LH.getNode() && !RH.getNode() &&
isOperationLegalOrCustom(ISD::SRL, VT) &&
isOperationLegalOrCustom(ISD::TRUNCATE, HiLoVT)) {
unsigned ShiftAmt = VT.getSizeInBits() - HiLoVT.getSizeInBits();
SDValue Shift = DAG.getConstant(ShiftAmt, getShiftAmountTy(VT));
LH = DAG.getNode(ISD::SRL, dl, VT, N->getOperand(0), Shift);
LH = DAG.getNode(ISD::TRUNCATE, dl, HiLoVT, LH);
RH = DAG.getNode(ISD::SRL, dl, VT, N->getOperand(1), Shift);
RH = DAG.getNode(ISD::TRUNCATE, dl, HiLoVT, RH);
}
if (!LH.getNode())
return false;
if (HasUMUL_LOHI) {
// Lo,Hi = umul LHS, RHS.
SDValue UMulLOHI = DAG.getNode(ISD::UMUL_LOHI, dl,
DAG.getVTList(HiLoVT, HiLoVT), LL, RL);
Lo = UMulLOHI;
Hi = UMulLOHI.getValue(1);
RH = DAG.getNode(ISD::MUL, dl, HiLoVT, LL, RH);
LH = DAG.getNode(ISD::MUL, dl, HiLoVT, LH, RL);
Hi = DAG.getNode(ISD::ADD, dl, HiLoVT, Hi, RH);
Hi = DAG.getNode(ISD::ADD, dl, HiLoVT, Hi, LH);
return true;
}
if (HasMULHU) {
Lo = DAG.getNode(ISD::MUL, dl, HiLoVT, LL, RL);
Hi = DAG.getNode(ISD::MULHU, dl, HiLoVT, LL, RL);
RH = DAG.getNode(ISD::MUL, dl, HiLoVT, LL, RH);
LH = DAG.getNode(ISD::MUL, dl, HiLoVT, LH, RL);
Hi = DAG.getNode(ISD::ADD, dl, HiLoVT, Hi, RH);
Hi = DAG.getNode(ISD::ADD, dl, HiLoVT, Hi, LH);
return true;
}
}
return false;
}