1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 11:13:28 +01:00

[CodeGen] Refactor DAGTypeLegalizer::ExpandIntRes_MULFIX. NFC

Restructured the code a little bit in preparation for adding
UMULFIXSAT. I think it will be easier to understand the code
if not interleaving the codegen for signed/unsigned/saturated
cases that much.

llvm-svn: 370569
This commit is contained in:
Bjorn Pettersson 2019-08-31 09:28:50 +00:00
parent 99b90b9e5c
commit de3fdb020d

View File

@ -2811,21 +2811,25 @@ void DAGTypeLegalizer::ExpandIntRes_MULFIX(SDNode *N, SDValue &Lo,
SDValue RHS = N->getOperand(1);
uint64_t Scale = N->getConstantOperandVal(2);
bool Saturating = N->getOpcode() == ISD::SMULFIXSAT;
EVT BoolVT = getSetCCResultType(VT);
SDValue Zero = DAG.getConstant(0, dl, VT);
bool Signed = (N->getOpcode() == ISD::SMULFIX ||
N->getOpcode() == ISD::SMULFIXSAT);
// Handle special case when scale is equal to zero.
if (!Scale) {
SDValue Result;
if (!Saturating) {
Result = DAG.getNode(ISD::MUL, dl, VT, LHS, RHS);
} else {
EVT BoolVT = getSetCCResultType(VT);
Result = DAG.getNode(ISD::SMULO, dl, DAG.getVTList(VT, BoolVT), LHS, RHS);
SDValue Product = Result.getValue(0);
SDValue Overflow = Result.getValue(1);
assert(Signed && "Unsigned saturation not supported (yet).");
APInt MinVal = APInt::getSignedMinValue(VTSize);
APInt MaxVal = APInt::getSignedMaxValue(VTSize);
SDValue SatMin = DAG.getConstant(MinVal, dl, VT);
SDValue SatMax = DAG.getConstant(MaxVal, dl, VT);
SDValue Zero = DAG.getConstant(0, dl, VT);
SDValue ProdNeg = DAG.getSetCC(dl, BoolVT, Product, Zero, ISD::SETLT);
Result = DAG.getSelect(dl, VT, ProdNeg, SatMax, SatMin);
Result = DAG.getSelect(dl, VT, Overflow, Result, Product);
@ -2840,8 +2844,6 @@ void DAGTypeLegalizer::ExpandIntRes_MULFIX(SDNode *N, SDValue &Lo,
GetExpandedInteger(RHS, RL, RH);
SmallVector<SDValue, 4> Result;
bool Signed = (N->getOpcode() == ISD::SMULFIX ||
N->getOpcode() == ISD::SMULFIXSAT);
unsigned LoHiOp = Signed ? ISD::SMUL_LOHI : ISD::UMUL_LOHI;
if (!TLI.expandMUL_LOHI(LoHiOp, VT, dl, LHS, RHS, Result, NVT, DAG,
TargetLowering::MulExpansionKind::OnlyLegalOrCustom,
@ -2855,19 +2857,14 @@ void DAGTypeLegalizer::ExpandIntRes_MULFIX(SDNode *N, SDValue &Lo,
"the size of the current value type");
EVT ShiftTy = TLI.getShiftAmountTy(NVT, DAG.getDataLayout());
// Shift whole amount by scale.
SDValue ResultLL = Result[0];
SDValue ResultLH = Result[1];
SDValue ResultHL = Result[2];
SDValue ResultHH = Result[3];
SDValue SatMax, SatMin;
SDValue NVTZero = DAG.getConstant(0, dl, NVT);
SDValue NVTNeg1 = DAG.getConstant(-1, dl, NVT);
EVT BoolNVT = getSetCCResultType(NVT);
// After getting the multplication result in 4 parts, we need to perform a
// After getting the multiplication result in 4 parts, we need to perform a
// shift right by the amount of the scale to get the result in that scale.
//
// Let's say we multiply 2 64 bit numbers. The resulting value can be held in
// 128 bits that are cut into 4 32-bit parts:
//
@ -2894,66 +2891,17 @@ void DAGTypeLegalizer::ExpandIntRes_MULFIX(SDNode *N, SDValue &Lo,
Hi = DAG.getNode(ISD::SRL, dl, NVT, ResultLH, SRLAmnt);
Hi = DAG.getNode(ISD::OR, dl, NVT, Hi,
DAG.getNode(ISD::SHL, dl, NVT, ResultHL, SHLAmnt));
// We cannot overflow past HH when multiplying 2 ints of size VTSize, so the
// highest bit of HH determines saturation direction in the event of
// saturation.
// The number of overflow bits we can check are VTSize - Scale + 1 (we
// include the sign bit). If these top bits are > 0, then we overflowed past
// the max value. If these top bits are < -1, then we overflowed past the
// min value. Otherwise, we did not overflow.
if (Saturating) {
unsigned OverflowBits = VTSize - Scale + 1;
assert(OverflowBits <= VTSize && OverflowBits > NVTSize &&
"Extent of overflow bits must start within HL");
SDValue HLHiMask = DAG.getConstant(
APInt::getHighBitsSet(NVTSize, OverflowBits - NVTSize), dl, NVT);
SDValue HLLoMask = DAG.getConstant(
APInt::getLowBitsSet(NVTSize, VTSize - OverflowBits), dl, NVT);
// HH > 0 or HH == 0 && HL > HLLoMask
SDValue HHPos = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTZero, ISD::SETGT);
SDValue HHZero = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTZero, ISD::SETEQ);
SDValue HLPos =
DAG.getSetCC(dl, BoolNVT, ResultHL, HLLoMask, ISD::SETUGT);
SatMax = DAG.getNode(ISD::OR, dl, BoolNVT, HHPos,
DAG.getNode(ISD::AND, dl, BoolNVT, HHZero, HLPos));
// HH < -1 or HH == -1 && HL < HLHiMask
SDValue HHNeg = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTNeg1, ISD::SETLT);
SDValue HHNeg1 = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTNeg1, ISD::SETEQ);
SDValue HLNeg =
DAG.getSetCC(dl, BoolNVT, ResultHL, HLHiMask, ISD::SETULT);
SatMin = DAG.getNode(ISD::OR, dl, BoolNVT, HHNeg,
DAG.getNode(ISD::AND, dl, BoolNVT, HHNeg1, HLNeg));
}
} else if (Scale == NVTSize) {
// If the scales are equal, Lo and Hi are ResultLH and Result HL,
// If the scales are equal, Lo and Hi are ResultLH and ResultHL,
// respectively. Avoid shifting to prevent undefined behavior.
Lo = ResultLH;
Hi = ResultHL;
// We overflow max if HH > 0 or HH == 0 && HL sign bit is 1.
// We overflow min if HH < -1 or HH == -1 && HL sign bit is 0.
if (Saturating) {
SDValue HHPos = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTZero, ISD::SETGT);
SDValue HHZero = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTZero, ISD::SETEQ);
SDValue HLNeg = DAG.getSetCC(dl, BoolNVT, ResultHL, NVTZero, ISD::SETLT);
SatMax = DAG.getNode(ISD::OR, dl, BoolNVT, HHPos,
DAG.getNode(ISD::AND, dl, BoolNVT, HHZero, HLNeg));
SDValue HHNeg = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTNeg1, ISD::SETLT);
SDValue HHNeg1 = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTNeg1, ISD::SETEQ);
SDValue HLPos = DAG.getSetCC(dl, BoolNVT, ResultHL, NVTZero, ISD::SETGE);
SatMin = DAG.getNode(ISD::OR, dl, BoolNVT, HHNeg,
DAG.getNode(ISD::AND, dl, BoolNVT, HHNeg1, HLPos));
}
} else if (Scale < VTSize) {
// If the scale is instead less than the old VT size, but greater than or
// equal to the expanded VT size, the first part of the result (ResultLL) is
// no longer a part of Lo because it would be scaled out anyway. Instead we
// can start shifting right from the fourth part (ResultHH) to the second
// part (ResultLH), and Result LH will be the new Lo.
// part (ResultLH), and ResultLH will be the new Lo.
SDValue SRLAmnt = DAG.getConstant(Scale - NVTSize, dl, ShiftTy);
SDValue SHLAmnt = DAG.getConstant(VTSize - Scale, dl, ShiftTy);
Lo = DAG.getNode(ISD::SRL, dl, NVT, ResultLH, SRLAmnt);
@ -2962,19 +2910,6 @@ void DAGTypeLegalizer::ExpandIntRes_MULFIX(SDNode *N, SDValue &Lo,
Hi = DAG.getNode(ISD::SRL, dl, NVT, ResultHL, SRLAmnt);
Hi = DAG.getNode(ISD::OR, dl, NVT, Hi,
DAG.getNode(ISD::SHL, dl, NVT, ResultHH, SHLAmnt));
// This is similar to the case when we saturate if Scale < NVTSize, but we
// only need to chech HH.
if (Saturating) {
unsigned OverflowBits = VTSize - Scale + 1;
SDValue HHHiMask = DAG.getConstant(
APInt::getHighBitsSet(NVTSize, OverflowBits), dl, NVT);
SDValue HHLoMask = DAG.getConstant(
APInt::getLowBitsSet(NVTSize, NVTSize - OverflowBits), dl, NVT);
SatMax = DAG.getSetCC(dl, BoolNVT, ResultHH, HHLoMask, ISD::SETGT);
SatMin = DAG.getSetCC(dl, BoolNVT, ResultHH, HHHiMask, ISD::SETLT);
}
} else if (Scale == VTSize) {
assert(
!Signed &&
@ -2982,20 +2917,90 @@ void DAGTypeLegalizer::ExpandIntRes_MULFIX(SDNode *N, SDValue &Lo,
Lo = ResultHL;
Hi = ResultHH;
} else {
} else
llvm_unreachable("Expected the scale to be less than or equal to the width "
"of the operands");
}
if (Saturating) {
APInt LHMax = APInt::getSignedMaxValue(NVTSize);
APInt LLMax = APInt::getAllOnesValue(NVTSize);
APInt LHMin = APInt::getSignedMinValue(NVTSize);
Hi = DAG.getSelect(dl, NVT, SatMax, DAG.getConstant(LHMax, dl, NVT), Hi);
Hi = DAG.getSelect(dl, NVT, SatMin, DAG.getConstant(LHMin, dl, NVT), Hi);
Lo = DAG.getSelect(dl, NVT, SatMax, DAG.getConstant(LLMax, dl, NVT), Lo);
Lo = DAG.getSelect(dl, NVT, SatMin, NVTZero, Lo);
}
// Unless saturation is requested we are done. The result is in <Hi,Lo>.
if (!Saturating)
return;
// To handle saturation we must check for overflow in the multiplication.
//
// Signed overflow happened if the upper (VTSize - Scale + 1) bits (of Result)
// aren't all ones or all zeroes.
//
// We cannot overflow past HH when multiplying 2 ints of size VTSize, so the
// highest bit of HH determines saturation direction in the event of
// saturation.
SDValue SatMax, SatMin;
SDValue NVTZero = DAG.getConstant(0, dl, NVT);
SDValue NVTNeg1 = DAG.getConstant(-1, dl, NVT);
EVT BoolNVT = getSetCCResultType(NVT);
if (!Signed)
llvm_unreachable("Unsigned saturation not supported (yet).");
if (Scale < NVTSize) {
// The number of overflow bits we can check are VTSize - Scale + 1 (we
// include the sign bit). If these top bits are > 0, then we overflowed past
// the max value. If these top bits are < -1, then we overflowed past the
// min value. Otherwise, we did not overflow.
unsigned OverflowBits = VTSize - Scale + 1;
assert(OverflowBits <= VTSize && OverflowBits > NVTSize &&
"Extent of overflow bits must start within HL");
SDValue HLHiMask = DAG.getConstant(
APInt::getHighBitsSet(NVTSize, OverflowBits - NVTSize), dl, NVT);
SDValue HLLoMask = DAG.getConstant(
APInt::getLowBitsSet(NVTSize, VTSize - OverflowBits), dl, NVT);
// We overflow max if HH > 0 or (HH == 0 && HL > HLLoMask).
SDValue HHGT0 = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTZero, ISD::SETGT);
SDValue HHEQ0 = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTZero, ISD::SETEQ);
SDValue HLUGT = DAG.getSetCC(dl, BoolNVT, ResultHL, HLLoMask, ISD::SETUGT);
SatMax = DAG.getNode(ISD::OR, dl, BoolNVT, HHGT0,
DAG.getNode(ISD::AND, dl, BoolNVT, HHEQ0, HLUGT));
// We overflow min if HH < -1 or (HH == -1 && HL < HLHiMask).
SDValue HHLT = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTNeg1, ISD::SETLT);
SDValue HHEQ = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTNeg1, ISD::SETEQ);
SDValue HLULT = DAG.getSetCC(dl, BoolNVT, ResultHL, HLHiMask, ISD::SETULT);
SatMin = DAG.getNode(ISD::OR, dl, BoolNVT, HHLT,
DAG.getNode(ISD::AND, dl, BoolNVT, HHEQ, HLULT));
} else if (Scale == NVTSize) {
// We overflow max if HH > 0 or (HH == 0 && HL sign bit is 1).
SDValue HHGT0 = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTZero, ISD::SETGT);
SDValue HHEQ0 = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTZero, ISD::SETEQ);
SDValue HLNeg = DAG.getSetCC(dl, BoolNVT, ResultHL, NVTZero, ISD::SETLT);
SatMax = DAG.getNode(ISD::OR, dl, BoolNVT, HHGT0,
DAG.getNode(ISD::AND, dl, BoolNVT, HHEQ0, HLNeg));
// We overflow min if HH < -1 or (HH == -1 && HL sign bit is 0).
SDValue HHLT = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTNeg1, ISD::SETLT);
SDValue HHEQ = DAG.getSetCC(dl, BoolNVT, ResultHH, NVTNeg1, ISD::SETEQ);
SDValue HLPos = DAG.getSetCC(dl, BoolNVT, ResultHL, NVTZero, ISD::SETGE);
SatMin = DAG.getNode(ISD::OR, dl, BoolNVT, HHLT,
DAG.getNode(ISD::AND, dl, BoolNVT, HHEQ, HLPos));
} else if (Scale < VTSize) {
// This is similar to the case when we saturate if Scale < NVTSize, but we
// only need to check HH.
unsigned OverflowBits = VTSize - Scale + 1;
SDValue HHHiMask = DAG.getConstant(
APInt::getHighBitsSet(NVTSize, OverflowBits), dl, NVT);
SDValue HHLoMask = DAG.getConstant(
APInt::getLowBitsSet(NVTSize, NVTSize - OverflowBits), dl, NVT);
SatMax = DAG.getSetCC(dl, BoolNVT, ResultHH, HHLoMask, ISD::SETGT);
SatMin = DAG.getSetCC(dl, BoolNVT, ResultHH, HHHiMask, ISD::SETLT);
} else
llvm_unreachable("Illegal scale for signed fixed point mul.");
// Saturate to signed maximum.
APInt MaxHi = APInt::getSignedMaxValue(NVTSize);
APInt MaxLo = APInt::getAllOnesValue(NVTSize);
Hi = DAG.getSelect(dl, NVT, SatMax, DAG.getConstant(MaxHi, dl, NVT), Hi);
Lo = DAG.getSelect(dl, NVT, SatMax, DAG.getConstant(MaxLo, dl, NVT), Lo);
// Saturate to signed minimum.
APInt MinHi = APInt::getSignedMinValue(NVTSize);
Hi = DAG.getSelect(dl, NVT, SatMin, DAG.getConstant(MinHi, dl, NVT), Hi);
Lo = DAG.getSelect(dl, NVT, SatMin, NVTZero, Lo);
}
void DAGTypeLegalizer::ExpandIntRes_SADDSUBO(SDNode *Node,