Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions llvm/include/llvm/CodeGen/BasicTTIImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,12 +316,22 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
EVT ScalarVT = VT.getScalarType();
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;

/// Migration flag. IsVectorCall cases directly know about the vector
/// libcall in RuntimeLibcallsInfo and shouldn't try to use
/// LibInfo->getVectorMappingInfo.
bool IsVectorCall = false;

switch (ICA.getID()) {
case Intrinsic::modf:
LC = RTLIB::getMODF(ScalarVT);
break;
case Intrinsic::sincospi:
LC = RTLIB::getSINCOSPI(ScalarVT);
LC = RTLIB::getSINCOSPI(VT);
if (LC == RTLIB::UNKNOWN_LIBCALL)
LC = RTLIB::getSINCOSPI(ScalarVT);
else if (VT.isVector())
IsVectorCall = true;

break;
case Intrinsic::sincos:
LC = RTLIB::getSINCOS(ScalarVT);
Expand All @@ -345,17 +355,23 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
LLVMContext &Ctx = RetTy->getContext();
ElementCount VF = getVectorizedTypeVF(RetTy);
VecDesc const *VD = nullptr;
for (bool Masked : {false, true}) {
if ((VD = LibInfo->getVectorMappingInfo(LCName, VF, Masked)))
break;

if (!IsVectorCall) {
for (bool Masked : {false, true}) {
if ((VD = LibInfo->getVectorMappingInfo(LCName, VF, Masked)))
break;
}
if (!VD)
return std::nullopt;
}
if (!VD)
return std::nullopt;

// Cost the call + mask.
auto Cost =
thisT()->getCallInstrCost(nullptr, RetTy, ICA.getArgTypes(), CostKind);
if (VD->isMasked()) {

if ((VD && VD->isMasked()) ||
(IsVectorCall &&
RTLIB::RuntimeLibcallsInfo::hasVectorMaskArgument(LibcallImpl))) {
auto VecTy = VectorType::get(IntegerType::getInt1Ty(Ctx), VF);
Cost += thisT()->getShuffleCost(TargetTransformInfo::SK_Broadcast, VecTy,
VecTy, {}, CostKind, 0, nullptr, {});
Expand Down
10 changes: 9 additions & 1 deletion llvm/include/llvm/CodeGen/SelectionDAG.h
Original file line number Diff line number Diff line change
Expand Up @@ -1725,9 +1725,17 @@ class SelectionDAG {
/// value.
LLVM_ABI bool
expandMultipleResultFPLibCall(RTLIB::Libcall LC, SDNode *Node,
SmallVectorImpl<SDValue> &Results,
SmallVectorImpl<SDValue> &Results, EVT CallType,
std::optional<unsigned> CallRetResNo = {});

// FIXME: Ths should be removed, and form using RTLIB::Libcall should be
// preferred. Callers should resolve the exact type libcall to use.
LLVM_ABI bool
expandMultipleResultFPLibCall(StringRef LibcallName, CallingConv::ID CC,
SDNode *Node, SmallVectorImpl<SDValue> &Results,
std::optional<unsigned> CallRetResNo = {},
bool IsVectorMasked = false);

/// Expand the specified \c ISD::VAARG node as the Legalize pass would.
LLVM_ABI SDValue expandVAArg(SDNode *Node);

Expand Down
15 changes: 5 additions & 10 deletions llvm/include/llvm/IR/RuntimeLibcalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,7 @@ struct RuntimeLibcallsInfo {
const Triple &TT,
ExceptionHandling ExceptionModel = ExceptionHandling::None,
FloatABI::ABIType FloatABI = FloatABI::Default,
EABI EABIVersion = EABI::Default, StringRef ABIName = "") {
// FIXME: The ExceptionModel parameter is to handle the field in
// TargetOptions. This interface fails to distinguish the forced disable
// case for targets which support exceptions by default. This should
// probably be a module flag and removed from TargetOptions.
if (ExceptionModel == ExceptionHandling::None)
ExceptionModel = TT.getDefaultExceptionHandling();

initLibcalls(TT, ExceptionModel, FloatABI, EABIVersion, ABIName);
}
EABI EABIVersion = EABI::Default, StringRef ABIName = "");

explicit RuntimeLibcallsInfo(const Module &M);

Expand Down Expand Up @@ -170,6 +161,10 @@ struct RuntimeLibcallsInfo {
getFunctionTy(LLVMContext &Ctx, const Triple &TT, const DataLayout &DL,
RTLIB::LibcallImpl LibcallImpl) const;

/// Returns true if the function has a vector mask argument, which is assumed
/// to be the last argument.
static bool hasVectorMaskArgument(RTLIB::LibcallImpl Impl);

private:
LLVM_ABI static iota_range<RTLIB::LibcallImpl>
lookupLibcallImplNameImpl(StringRef Name);
Expand Down
43 changes: 38 additions & 5 deletions llvm/include/llvm/IR/RuntimeLibcalls.td
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ foreach FPTy = ["F32", "F64", "F80", "F128", "PPCF128"] in {
def MODF_#FPTy : RuntimeLibcall;
}

foreach VecTy = ["V4F32", "V2F64", "NXV4F32", "NXV2F64"] in {
def SINCOSPI_#VecTy : RuntimeLibcall;
}

def FEGETENV : RuntimeLibcall;
def FESETENV : RuntimeLibcall;

Expand Down Expand Up @@ -971,10 +975,6 @@ def frexpf : RuntimeLibcallImpl<FREXP_F32>;
def frexp : RuntimeLibcallImpl<FREXP_F64>;
defm frexpl : LibmLongDoubleLibCall;

def sincospif : RuntimeLibcallImpl<SINCOSPI_F32>;
def sincospi : RuntimeLibcallImpl<SINCOSPI_F64>;
defm sincospil : LibmLongDoubleLibCall;

def modff : RuntimeLibcallImpl<MODF_F32>;
def modf : RuntimeLibcallImpl<MODF_F64>;
defm modfl : LibmLongDoubleLibCall;
Expand Down Expand Up @@ -1051,6 +1051,15 @@ def sincosf : RuntimeLibcallImpl<SINCOS_F32>;
def sincos : RuntimeLibcallImpl<SINCOS_F64>;
defm sincosl : LibmLongDoubleLibCall;

// Exists in sun math library
def sincospif : RuntimeLibcallImpl<SINCOSPI_F32>;
def sincospi : RuntimeLibcallImpl<SINCOSPI_F64>;
defm sincospil : LibmLongDoubleLibCall;

// Exists on macOS
def __sincospif : RuntimeLibcallImpl<SINCOSPI_F32>;
def __sincospi : RuntimeLibcallImpl<SINCOSPI_F64>;

def bzero : RuntimeLibcallImpl<BZERO>;
def __bzero : RuntimeLibcallImpl<BZERO>;

Expand Down Expand Up @@ -1078,6 +1087,28 @@ def __security_check_cookie : RuntimeLibcallImpl<SECURITY_CHECK_COOKIE>;
def __security_check_cookie_arm64ec : RuntimeLibcallImpl<SECURITY_CHECK_COOKIE,
"#__security_check_cookie_arm64ec">;

//===----------------------------------------------------------------------===//
// sleef calls
//===----------------------------------------------------------------------===//

defset list<RuntimeLibcallImpl> SleefLibcalls = {
def _ZGVnN4vl4l4_sincospif : RuntimeLibcallImpl<SINCOSPI_V4F32>;
def _ZGVnN2vl8l8_sincospi : RuntimeLibcallImpl<SINCOSPI_V2F64>;
def _ZGVsNxvl4l4_sincospif : RuntimeLibcallImpl<SINCOSPI_NXV4F32>;
def _ZGVsNxvl8l8_sincospi : RuntimeLibcallImpl<SINCOSPI_NXV2F64>;
}

//===----------------------------------------------------------------------===//
// ARMPL calls
//===----------------------------------------------------------------------===//

defset list<RuntimeLibcallImpl> ARMPLLibcalls = {
def armpl_vsincospiq_f32 : RuntimeLibcallImpl<SINCOSPI_V4F32>;
def armpl_vsincospiq_f64 : RuntimeLibcallImpl<SINCOSPI_V2F64>;
def armpl_svsincospi_f32_x : RuntimeLibcallImpl<SINCOSPI_NXV4F32>;
def armpl_svsincospi_f64_x : RuntimeLibcallImpl<SINCOSPI_NXV2F64>;
}

//===----------------------------------------------------------------------===//
// F128 libm Runtime Libcalls
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1206,7 +1237,9 @@ defvar DefaultLibcallImpls32 = (add DefaultRuntimeLibcallImpls);
defvar DefaultLibcallImpls64 = (add DefaultRuntimeLibcallImpls,
Int128RTLibcalls);

defvar DarwinSinCosStret = LibcallImpls<(add __sincosf_stret, __sincos_stret),
// TODO: Guessing sincospi added at same time as sincos_stret
defvar DarwinSinCosStret = LibcallImpls<(add __sincosf_stret, __sincos_stret,
__sincospif, __sincospi),
darwinHasSinCosStret>;
defvar DarwinExp10 = LibcallImpls<(add __exp10f, __exp10), darwinHasExp10>;

Expand Down
14 changes: 10 additions & 4 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4842,9 +4842,15 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
RTLIB::Libcall LC = Node->getOpcode() == ISD::FSINCOS
? RTLIB::getSINCOS(VT)
: RTLIB::getSINCOSPI(VT);
bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results);
if (!Expanded)
llvm_unreachable("Expected scalar FSINCOS[PI] to expand to libcall!");
bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results, VT);
if (!Expanded) {
DAG.getContext()->emitError(Twine("no libcall available for ") +
Node->getOperationName(&DAG));
SDValue Poison = DAG.getPOISON(VT);
Results.push_back(Poison);
Results.push_back(Poison);
}

break;
}
case ISD::FLOG:
Expand Down Expand Up @@ -4934,7 +4940,7 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
EVT VT = Node->getValueType(0);
RTLIB::Libcall LC = Node->getOpcode() == ISD::FMODF ? RTLIB::getMODF(VT)
: RTLIB::getFREXP(VT);
bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results,
bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results, VT,
/*CallRetResNo=*/0);
if (!Expanded)
llvm_unreachable("Expected scalar FFREXP/FMODF to expand to libcall!");
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1726,7 +1726,8 @@ void DAGTypeLegalizer::ExpandFloatRes_UnaryWithTwoFPResults(
SDNode *N, RTLIB::Libcall LC, std::optional<unsigned> CallRetResNo) {
assert(!N->isStrictFPOpcode() && "strictfp not implemented");
SmallVector<SDValue> Results;
DAG.expandMultipleResultFPLibCall(LC, N, Results, CallRetResNo);
DAG.expandMultipleResultFPLibCall(LC, N, Results, N->getValueType(0),
CallRetResNo);
for (auto [ResNo, Res] : enumerate(Results)) {
SDValue Lo, Hi;
GetPairElements(Res, Lo, Hi);
Expand Down
26 changes: 18 additions & 8 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1268,20 +1268,30 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
return;

break;
case ISD::FSINCOS:

case ISD::FSINCOSPI: {
EVT VT = Node->getValueType(0);
RTLIB::Libcall LC = RTLIB::getSINCOSPI(VT);
if (LC != RTLIB::UNKNOWN_LIBCALL &&
DAG.expandMultipleResultFPLibCall(LC, Node, Results, VT))
return;

// TODO: Try to see if there's a narrower call available to use before
// scalarizing.
break;
}
case ISD::FSINCOS: {
// FIXME: Try to directly match vector case like fsincospi
EVT VT = Node->getValueType(0).getVectorElementType();
RTLIB::Libcall LC = Node->getOpcode() == ISD::FSINCOS
? RTLIB::getSINCOS(VT)
: RTLIB::getSINCOSPI(VT);
if (DAG.expandMultipleResultFPLibCall(LC, Node, Results))
RTLIB::Libcall LC = RTLIB::getSINCOS(VT);
if (DAG.expandMultipleResultFPLibCall(LC, Node, Results, VT))
return;
break;
}
case ISD::FMODF: {
RTLIB::Libcall LC =
RTLIB::getMODF(Node->getValueType(0).getVectorElementType());
if (DAG.expandMultipleResultFPLibCall(LC, Node, Results,
EVT VT = Node->getValueType(0).getVectorElementType();
RTLIB::Libcall LC = RTLIB::getMODF(VT);
if (DAG.expandMultipleResultFPLibCall(LC, Node, Results, VT,
/*CallRetResNo=*/0))
return;
break;
Expand Down
53 changes: 40 additions & 13 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2514,18 +2514,20 @@ static bool canFoldStoreIntoLibCallOutputPointers(StoreSDNode *StoreNode,

bool SelectionDAG::expandMultipleResultFPLibCall(
RTLIB::Libcall LC, SDNode *Node, SmallVectorImpl<SDValue> &Results,
std::optional<unsigned> CallRetResNo) {
LLVMContext &Ctx = *getContext();
EVT VT = Node->getValueType(0);
unsigned NumResults = Node->getNumValues();

EVT CallVT, std::optional<unsigned> CallRetResNo) {
if (LC == RTLIB::UNKNOWN_LIBCALL)
return false;

const char *LCName = TLI->getLibcallName(LC);
if (!LCName)
EVT VT = Node->getValueType(0);

RTLIB::LibcallImpl Impl = TLI->getLibcallImpl(LC);
if (Impl == RTLIB::Unsupported)
return false;

StringRef LCName = TLI->getLibcallImplName(Impl);

// FIXME: This should not use TargetLibraryInfo. There should be
// RTLIB::Libcall entries for each used vector type, and directly matched.
auto getVecDesc = [&]() -> VecDesc const * {
for (bool Masked : {false, true}) {
if (VecDesc const *VD = getLibInfo().getVectorMappingInfo(
Expand All @@ -2538,9 +2540,34 @@ bool SelectionDAG::expandMultipleResultFPLibCall(

// For vector types, we must find a vector mapping for the libcall.
VecDesc const *VD = nullptr;
if (VT.isVector() && !(VD = getVecDesc()))
if (VT.isVector() && !CallVT.isVector() && !(VD = getVecDesc()))
return false;

bool IsMasked = (VD && VD->isMasked()) ||
RTLIB::RuntimeLibcallsInfo::hasVectorMaskArgument(Impl);

// This wrapper function exists because getVectorMappingInfo works in terms of
// function names instead of RTLIB enums.

// FIXME: If we used a vector mapping, this assumes the calling convention of
// the vector function is the same as the scalar.

StringRef Name = VD ? VD->getVectorFnName() : LCName;

return expandMultipleResultFPLibCall(Name,
TLI->getLibcallImplCallingConv(Impl),
Node, Results, CallRetResNo, IsMasked);
}

// FIXME: This belongs in TargetLowering
bool SelectionDAG::expandMultipleResultFPLibCall(
StringRef Name, CallingConv::ID CC, SDNode *Node,
SmallVectorImpl<SDValue> &Results, std::optional<unsigned> CallRetResNo,
bool IsMasked) {
LLVMContext &Ctx = *getContext();
EVT VT = Node->getValueType(0);
unsigned NumResults = Node->getNumValues();

// Find users of the node that store the results (and share input chains). The
// destination pointers can be used instead of creating stack allocations.
SDValue StoresInChain;
Expand Down Expand Up @@ -2598,7 +2625,7 @@ bool SelectionDAG::expandMultipleResultFPLibCall(
SDLoc DL(Node);

// Pass the vector mask (if required).
if (VD && VD->isMasked()) {
if (IsMasked) {
EVT MaskVT = TLI->getSetCCResultType(getDataLayout(), Ctx, VT);
SDValue Mask = getBoolConstant(true, DL, MaskVT, VT);
Args.emplace_back(Mask, MaskVT.getTypeForEVT(Ctx));
Expand All @@ -2608,11 +2635,11 @@ bool SelectionDAG::expandMultipleResultFPLibCall(
? Node->getValueType(*CallRetResNo).getTypeForEVT(Ctx)
: Type::getVoidTy(Ctx);
SDValue InChain = StoresInChain ? StoresInChain : getEntryNode();
SDValue Callee = getExternalSymbol(VD ? VD->getVectorFnName().data() : LCName,
TLI->getPointerTy(getDataLayout()));
SDValue Callee =
getExternalSymbol(Name.data(), TLI->getPointerTy(getDataLayout()));
TargetLowering::CallLoweringInfo CLI(*this);
CLI.setDebugLoc(DL).setChain(InChain).setLibCallee(
TLI->getLibcallCallingConv(LC), RetType, Callee, std::move(Args));
CLI.setDebugLoc(DL).setChain(InChain).setLibCallee(CC, RetType, Callee,
std::move(Args));

auto [Call, CallChain] = TLI->LowerCallTo(CLI);

Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/CodeGen/TargetLoweringBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,24 @@ RTLIB::Libcall RTLIB::getSINCOS(EVT RetVT) {
}

RTLIB::Libcall RTLIB::getSINCOSPI(EVT RetVT) {
// TODO: Tablegen should generate this function
if (RetVT.isVector()) {
if (!RetVT.isSimple())
return RTLIB::UNKNOWN_LIBCALL;
switch (RetVT.getSimpleVT().SimpleTy) {
case MVT::v4f32:
return RTLIB::SINCOSPI_V4F32;
case MVT::v2f64:
return RTLIB::SINCOSPI_V2F64;
case MVT::nxv4f32:
return RTLIB::SINCOSPI_NXV4F32;
case MVT::nxv2f64:
return RTLIB::SINCOSPI_NXV2F64;
default:
return RTLIB::UNKNOWN_LIBCALL;
}
}

return getFPLibCall(RetVT, SINCOSPI_F32, SINCOSPI_F64, SINCOSPI_F80,
SINCOSPI_F128, SINCOSPI_PPCF128);
}
Expand Down
Loading
Loading