forked from OSchip/llvm-project
[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:
parent
77e8f4eeee
commit
b2ca4dc935
|
@ -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.
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue