[LegalizeTypes] Add a simple expansion for SMULO when a libcall isn't available.

This isn't optimal, but prevents crashing when the libcall isn't
available. It just calculates the full product and makes sure the high bits
match the sign of the low half. Each of the pieces should go through their own
type legalization.

This can make D107420 unnecessary.

Needs tests, but I wanted to start discussion about D107420.

Reviewed By: FreddyYe

Differential Revision: https://reviews.llvm.org/D107581
This commit is contained in:
Craig Topper 2021-08-06 09:31:05 -07:00
parent 77e8f4eeee
commit b2ca4dc935
3 changed files with 1559 additions and 1 deletions

View File

@ -4045,7 +4045,25 @@ void DAGTypeLegalizer::ExpandIntRes_XMULO(SDNode *N,
LC = RTLIB::MULO_I64;
else if (VT == MVT::i128)
LC = RTLIB::MULO_I128;
assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XMULO!");
if (LC == RTLIB::UNKNOWN_LIBCALL || !TLI.getLibcallName(LC)) {
// FIXME: This is not an optimal expansion, but better than crashing.
EVT WideVT =
EVT::getIntegerVT(*DAG.getContext(), VT.getScalarSizeInBits() * 2);
SDValue LHS = DAG.getNode(ISD::SIGN_EXTEND, dl, WideVT, N->getOperand(0));
SDValue RHS = DAG.getNode(ISD::SIGN_EXTEND, dl, WideVT, N->getOperand(1));
SDValue Mul = DAG.getNode(ISD::MUL, dl, WideVT, LHS, RHS);
SDValue MulLo, MulHi;
SplitInteger(Mul, MulLo, MulHi);
SDValue SRA =
DAG.getNode(ISD::SRA, dl, VT, MulLo,
DAG.getConstant(VT.getScalarSizeInBits() - 1, dl, VT));
SDValue Overflow =
DAG.getSetCC(dl, N->getValueType(1), MulHi, SRA, ISD::SETNE);
SplitInteger(MulLo, Lo, Hi);
ReplaceValueWith(SDValue(N, 1), Overflow);
return;
}
SDValue Temp = DAG.CreateStackTemporary(PtrVT);
// Temporary for the overflow value, default it to zero.

View File

@ -1962,6 +1962,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setLibcallName(RTLIB::SRL_I128, nullptr);
setLibcallName(RTLIB::SRA_I128, nullptr);
setLibcallName(RTLIB::MUL_I128, nullptr);
setLibcallName(RTLIB::MULO_I128, nullptr);
}
// Combine sin / cos into _sincos_stret if it is available.

File diff suppressed because it is too large Load Diff