Skip to content

Commit 2fd1d47

Browse files
committed
[IR] Change fp128 lowering to use f128 functions by default
LLVM currently emits calls to `*l` (`long double`) libm symbols for `fp128` intrinsics. This works on platforms where `long double` and `_Float128` are the same type, but is incorrect on many platforms. Change RuntimeLibcalls such that `*f128` libcalls are used by default, which is always safe and correct but may not be available. On platforms where it is likely that `sqrtf128` and similar are not available, keep the current behavior of lowering to `*l` symbols if `long double` is `binary128`. The logic for whether f128 is `long double` is based on the platforms in Clang that set `LongDoubleFormat` to `llvm::APFloat::IEEEquad`. Fixes #44744
1 parent 853c948 commit 2fd1d47

30 files changed

+438
-329
lines changed

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3564,7 +3564,8 @@ class LLVM_ABI TargetLoweringBase {
35643564
return Libcalls.getLibcallImpl(Call);
35653565
}
35663566

3567-
/// Get the libcall routine name for the specified libcall.
3567+
/// Get the libcall routine name for the specified libcall if implemented,
3568+
/// otherwise NULL.
35683569
const char *getLibcallName(RTLIB::Libcall Call) const {
35693570
return Libcalls.getLibcallName(Call);
35703571
}

llvm/include/llvm/IR/RuntimeLibcalls.td

Lines changed: 92 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ def isOSWindows : RuntimeLibcallPredicate<"TT.isOSWindows()">;
2222
def darwinHasSinCosStret : RuntimeLibcallPredicate<"darwinHasSinCosStret(TT)">;
2323
def darwinHasExp10 : RuntimeLibcallPredicate<"darwinHasExp10(TT)">;
2424
def hasSinCos : RuntimeLibcallPredicate<"hasSinCos(TT)">;
25+
def f128LibmShouldUseLongDouble
26+
: RuntimeLibcallPredicate<"f128LibmShouldUseLongDouble(TT)">;
2527

2628
//--------------------------------------------------------------------
2729
// Declare all kinds of used libcalls
@@ -352,6 +354,9 @@ def MIPS16_RET_DF : RuntimeLibcall;
352354
def MIPS16_RET_SC : RuntimeLibcall;
353355
def MIPS16_RET_SF : RuntimeLibcall;
354356

357+
// Create libcall impls for `long double` and `_Float128`. See also `_ld128`
358+
// impls defined at `LibmF128AsLongDoubleLibcalls`.
359+
355360
// Produce libcall impls for all float types. If provided, `rtbasename` should
356361
// contain an `X` that will be replaced with the `f`/`l`/`fX` suffix (if not
357362
// provided, it is appended to the def name).
@@ -365,7 +370,7 @@ multiclass LibmLibcallImpls<string libcall_basename = !toupper(NAME),
365370
!subst("X", "", rtbasename)>;
366371
def NAME#"_f128"
367372
: RuntimeLibcallImpl<!cast<RuntimeLibcall>(libcall_basename#"_F128"),
368-
!subst("X", "l", rtbasename)>;
373+
!subst("X", "f128", rtbasename)>;
369374
def NAME#"_ppcf128"
370375
: RuntimeLibcallImpl<!cast<RuntimeLibcall>(libcall_basename#"_PPCF128"),
371376
!subst("X", "l", rtbasename)>;
@@ -374,6 +379,13 @@ multiclass LibmLibcallImpls<string libcall_basename = !toupper(NAME),
374379
!subst("X", "l", rtbasename)>;
375380
}
376381

382+
multiclass LibmF128AsLongDoubleImpls<string libcall_basename = !toupper(NAME),
383+
string rtbasename = !strconcat(NAME, "X")> {
384+
def NAME#"_ld128"
385+
: RuntimeLibcallImpl<!cast<RuntimeLibcall>(libcall_basename#"_F128"),
386+
!subst("X", "l", rtbasename)>;
387+
}
388+
377389
// AArch64 calls
378390
def SC_MEMCPY : RuntimeLibcall;
379391
def SC_MEMMOVE : RuntimeLibcall;
@@ -796,60 +808,61 @@ def _Unwind_SjLj_Resume : RuntimeLibcallImpl<UNWIND_RESUME>;
796808
// F128 libm Runtime Libcalls
797809
//===----------------------------------------------------------------------===//
798810

799-
defset list<RuntimeLibcallImpl> LibmF128Libcalls = {
800-
def logf128 : RuntimeLibcallImpl<LOG_F128>;
801-
def log2f128 : RuntimeLibcallImpl<LOG2_F128>;
802-
def log10f128 : RuntimeLibcallImpl<LOG10_F128>;
803-
def expf128 : RuntimeLibcallImpl<EXP_F128>;
804-
def exp2f128 : RuntimeLibcallImpl<EXP2_F128>;
805-
def exp10f128 : RuntimeLibcallImpl<EXP10_F128>;
806-
def sinf128 : RuntimeLibcallImpl<SIN_F128>;
807-
def cosf128 : RuntimeLibcallImpl<COS_F128>;
808-
def tanf128 : RuntimeLibcallImpl<TAN_F128>;
809-
def tanhf128 : RuntimeLibcallImpl<TANH_F128>;
810-
def sincosf128 : RuntimeLibcallImpl<SINCOS_F128>;
811-
def powf128 : RuntimeLibcallImpl<POW_F128>;
812-
def fminf128 : RuntimeLibcallImpl<FMIN_F128>;
813-
def fmaxf128 : RuntimeLibcallImpl<FMAX_F128>;
814-
def fmodf128 : RuntimeLibcallImpl<REM_F128>;
815-
def sqrtf128 : RuntimeLibcallImpl<SQRT_F128>;
816-
def ceilf128 : RuntimeLibcallImpl<CEIL_F128>;
817-
def floorf128 : RuntimeLibcallImpl<FLOOR_F128>;
818-
def truncf128 : RuntimeLibcallImpl<TRUNC_F128>;
819-
def roundf128 : RuntimeLibcallImpl<ROUND_F128>;
820-
def lroundf128 : RuntimeLibcallImpl<LROUND_F128>;
821-
def llroundf128 : RuntimeLibcallImpl<LLROUND_F128>;
822-
def rintf128 : RuntimeLibcallImpl<RINT_F128>;
823-
def lrintf128 : RuntimeLibcallImpl<LRINT_F128>;
824-
def llrintf128 : RuntimeLibcallImpl<LLRINT_F128>;
825-
def nearbyintf128 : RuntimeLibcallImpl<NEARBYINT_F128>;
826-
def fmaf128 : RuntimeLibcallImpl<FMA_F128>;
827-
def frexpf128 : RuntimeLibcallImpl<FREXP_F128>;
828-
def cbrtf128 : RuntimeLibcallImpl<CBRT_F128>;
829-
def fminimumf128 : RuntimeLibcallImpl<FMINIMUM_F128>;
830-
def fmaximumf128 : RuntimeLibcallImpl<FMAXIMUM_F128>;
831-
def fminimum_numf128 : RuntimeLibcallImpl<FMINIMUM_NUM_F128>;
832-
def fmaximum_numf128 : RuntimeLibcallImpl<FMAXIMUM_NUM_F128>;
833-
def asinf128 : RuntimeLibcallImpl<ASIN_F128>;
834-
def acosf128 : RuntimeLibcallImpl<ACOS_F128>;
835-
def atanf128 : RuntimeLibcallImpl<ATAN_F128>;
836-
def atan2f128 : RuntimeLibcallImpl<ATAN2_F128>;
837-
def ldexpf128 : RuntimeLibcallImpl<LDEXP_F128>;
838-
def roundevenf128 : RuntimeLibcallImpl<ROUNDEVEN_F128>;
839-
def modff128 : RuntimeLibcallImpl<MODF_F128>;
840-
def sinhf128 : RuntimeLibcallImpl<SINH_F128>;
841-
def coshf128 : RuntimeLibcallImpl<COSH_F128>;
842-
def copysignf128 : RuntimeLibcallImpl<COPYSIGN_F128>;
811+
// Impls for treating `fp128` as `long double`
812+
defset list<RuntimeLibcallImpl> LibmF128AsLongDoubleLibcalls = {
813+
defm log : LibmF128AsLongDoubleImpls;
814+
defm log2 : LibmF128AsLongDoubleImpls;
815+
defm log10 : LibmF128AsLongDoubleImpls;
816+
defm exp : LibmF128AsLongDoubleImpls;
817+
defm exp2 : LibmF128AsLongDoubleImpls;
818+
defm exp10 : LibmF128AsLongDoubleImpls;
819+
defm sin : LibmF128AsLongDoubleImpls;
820+
defm cos : LibmF128AsLongDoubleImpls;
821+
defm tan : LibmF128AsLongDoubleImpls;
822+
defm tanh : LibmF128AsLongDoubleImpls;
823+
defm sincos : LibmF128AsLongDoubleImpls;
824+
defm pow : LibmF128AsLongDoubleImpls;
825+
defm fmin : LibmF128AsLongDoubleImpls;
826+
defm fmax : LibmF128AsLongDoubleImpls;
827+
defm fmod : LibmF128AsLongDoubleImpls<"REM">;
828+
defm sqrt : LibmF128AsLongDoubleImpls;
829+
defm ceil : LibmF128AsLongDoubleImpls;
830+
defm floor : LibmF128AsLongDoubleImpls;
831+
defm trunc : LibmF128AsLongDoubleImpls;
832+
defm round : LibmF128AsLongDoubleImpls;
833+
defm lround : LibmF128AsLongDoubleImpls;
834+
defm llround : LibmF128AsLongDoubleImpls;
835+
defm rint : LibmF128AsLongDoubleImpls;
836+
defm lrint : LibmF128AsLongDoubleImpls;
837+
defm llrint : LibmF128AsLongDoubleImpls;
838+
defm nearbyint : LibmF128AsLongDoubleImpls;
839+
defm fma : LibmF128AsLongDoubleImpls;
840+
defm frexp : LibmF128AsLongDoubleImpls;
841+
defm cbrt : LibmF128AsLongDoubleImpls;
842+
defm fminimum : LibmF128AsLongDoubleImpls;
843+
defm fmaximum : LibmF128AsLongDoubleImpls;
844+
defm fminimum_num : LibmF128AsLongDoubleImpls;
845+
defm fmaximum_num : LibmF128AsLongDoubleImpls;
846+
defm asin : LibmF128AsLongDoubleImpls;
847+
defm acos : LibmF128AsLongDoubleImpls;
848+
defm atan : LibmF128AsLongDoubleImpls;
849+
defm atan2 : LibmF128AsLongDoubleImpls;
850+
defm ldexp : LibmF128AsLongDoubleImpls;
851+
defm roundeven : LibmF128AsLongDoubleImpls;
852+
defm modf : LibmF128AsLongDoubleImpls;
853+
defm sinh : LibmF128AsLongDoubleImpls;
854+
defm cosh : LibmF128AsLongDoubleImpls;
855+
defm copysign : LibmF128AsLongDoubleImpls;
843856
}
844857

845-
defset list<RuntimeLibcallImpl> LibmF128FiniteLibcalls = {
846-
def __logf128_finite : RuntimeLibcallImpl<LOG_FINITE_F128>;
847-
def __log2f128_finite : RuntimeLibcallImpl<LOG2_FINITE_F128>;
848-
def __log10f128_finite : RuntimeLibcallImpl<LOG10_FINITE_F128>;
849-
def __expf128_finite : RuntimeLibcallImpl<EXP_FINITE_F128>;
850-
def __exp2f128_finite : RuntimeLibcallImpl<EXP2_FINITE_F128>;
851-
def __exp10f128_finite : RuntimeLibcallImpl<EXP10_FINITE_F128>;
852-
def __powf128_finite : RuntimeLibcallImpl<POW_FINITE_F128>;
858+
defset list<RuntimeLibcallImpl> LibmF128AsLongDoubleFiniteLibcalls = {
859+
defm __log_finite : LibmF128AsLongDoubleImpls<"LOG_FINITE", "__logX_finite">;
860+
defm __log2_finite : LibmF128AsLongDoubleImpls<"LOG2_FINITE", "__log2X_finite">;
861+
defm __log10_finite : LibmF128AsLongDoubleImpls<"LOG10_FINITE", "__log10X_finite">;
862+
defm __exp_finite : LibmF128AsLongDoubleImpls<"EXP_FINITE", "__expX_finite">;
863+
defm __exp2_finite : LibmF128AsLongDoubleImpls<"EXP2_FINITE", "__exp2X_finite">;
864+
defm __exp10_finite : LibmF128AsLongDoubleImpls<"EXP10_FINITE", "__exp10X_finite">;
865+
defm __pow_finite : LibmF128AsLongDoubleImpls<"POW_FINITE", "__powX_finite">;
853866
}
854867

855868
//===----------------------------------------------------------------------===//
@@ -880,10 +893,6 @@ defvar DefaultRuntimeLibcallImpls =
880893
Int128RTLibcalls),
881894
CompilerRTOnlyInt128Libcalls);
882895

883-
defvar DefaultRuntimeLibcallImpls_f128 =
884-
!filter(entry, DefaultRuntimeLibcallImpls,
885-
!match(!cast<string>(entry.Provides), "_F128"));
886-
887896
defvar DefaultRuntimeLibcallImpls_atomic =
888897
!filter(entry, DefaultRuntimeLibcallImpls,
889898
!match(!cast<string>(entry.Provides), "ATOMIC"));
@@ -1658,7 +1667,7 @@ def NVPTXSystemLibrary : SystemRuntimeLibrary<isNVPTX, (add)>;
16581667
//===----------------------------------------------------------------------===//
16591668

16601669
// For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf".
1661-
defset list<RuntimeLibcallImpl> PPCRuntimeLibcalls = {
1670+
defset list<RuntimeLibcallImpl> PPCOverriddenRuntimeLibcalls = {
16621671
def __addkf3 : RuntimeLibcallImpl<ADD_F128>;
16631672
def __subkf3 : RuntimeLibcallImpl<SUB_F128>;
16641673
def __mulkf3 : RuntimeLibcallImpl<MUL_F128>;
@@ -1702,7 +1711,22 @@ defset list<RuntimeLibcallImpl> PPC32AIXCallList = {
17021711
def ___bzero : RuntimeLibcallImpl<BZERO>;
17031712
}
17041713

1705-
defvar PPCOverrides = !foreach(entry, PPCRuntimeLibcalls, entry.Provides);
1714+
// List of overriden libcalls as strings, `["ADD_F128", "SUB_F128", ...]`
1715+
defvar PPCOverriddenNames = !foreach(
1716+
entry, PPCOverriddenRuntimeLibcalls,
1717+
!cast<string>(entry.Provides)
1718+
);
1719+
1720+
// Default libcalls except for those that appear in `PPCOverrideNames`
1721+
defvar PPCNonOverriddenImpls = !filter(
1722+
default_entry, DefaultRuntimeLibcallImpls,
1723+
// `!contains` does not exist, `not->empty->filter` is a slightly hacky way
1724+
!not(!empty(!filter(
1725+
overridden,
1726+
PPCOverriddenNames,
1727+
!eq(overridden, !cast<string>(default_entry.Provides))
1728+
)))
1729+
);
17061730

17071731
def isPPC : RuntimeLibcallPredicate<"TT.isPPC()">;
17081732
def isPPC32 : RuntimeLibcallPredicate<"TT.isPPC32()">;
@@ -1715,17 +1739,21 @@ def isPPC64_AIX : RuntimeLibcallPredicate<"(TT.isPPC64() && TT.isOSAIX())">;
17151739
def AIX32Calls : LibcallImpls<(add PPC32AIXCallList), isPPC32_AIX>;
17161740
def AIX64Calls : LibcallImpls<(add PPC64AIXCallList), isPPC64_AIX>;
17171741

1742+
// Replace overridden values, adjust mem* symbols, add ppc_f128<->f128
1743+
// conversions.
1744+
defvar PPCDefaultRuntimeLibcallImpls =
1745+
(add (sub DefaultRuntimeLibcallImpls, PPCNonOverriddenImpls, memcpy),
1746+
PPCOverriddenRuntimeLibcalls ,
1747+
__extendkftf2, __trunctfkf2,
1748+
AIX32Calls, AIX64Calls);
1749+
17181750
// FIXME: Current emission behavior with multiple implementations is
17191751
// janky. We need to filter out the conflicting cases with different
17201752
// f128 names, and then add the overrides. We should switch to
17211753
// explicitly adding subsets of the default calls.
17221754
def PPCSystemLibrary
17231755
: SystemRuntimeLibrary<isPPC,
1724-
(add PPCRuntimeLibcalls,
1725-
(sub DefaultRuntimeLibcallImpls, memcpy,
1726-
DefaultRuntimeLibcallImpls_f128),
1727-
__extendkftf2, __trunctfkf2,
1728-
LibmF128Libcalls, AIX32Calls, AIX64Calls,
1756+
(add PPCDefaultRuntimeLibcallImpls,
17291757
AvailableIf<memcpy, isNotAIX>,
17301758
LibcallImpls<(add Int128RTLibcalls), isPPC64>)>;
17311759

llvm/include/llvm/TargetParser/Triple.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -266,13 +266,13 @@ class Triple {
266266
EABIHF,
267267
Android,
268268
Musl,
269-
MuslABIN32,
270-
MuslABI64,
271-
MuslEABI,
272-
MuslEABIHF,
273-
MuslF32,
274-
MuslSF,
275-
MuslX32,
269+
MuslABIN32, ///< MIPS N32 ABI
270+
MuslABI64, ///< MIPS N64 ABI
271+
MuslEABI, ///< Arm32 EABI
272+
MuslEABIHF, ///< Arm32 EABI + HF
273+
MuslF32, ///< LoongArch ILP32F/LP64F
274+
MuslSF, ///< LoongArch ILP32S/LP64S
275+
MuslX32, ///< Musl using 32-bit ABI on x86_64
276276
LLVM,
277277

278278
MSVC,
@@ -1274,6 +1274,10 @@ class Triple {
12741274
/// or an invalid version tuple if this triple doesn't have one.
12751275
LLVM_ABI VersionTuple getMinimumSupportedOSVersion() const;
12761276

1277+
/// Return true if `_Float128` libcalls should lower to e.g. `sqrtf` (`long
1278+
/// double`) rather than the default `sqrtf128`.
1279+
bool f128LibmShouldUseLongDouble() const;
1280+
12771281
/// @}
12781282
/// @name Static helpers for IDs.
12791283
/// @{

llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,10 @@ TargetLowering::makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT,
182182
}
183183

184184
const char *LibcallName = getLibcallName(LC);
185-
if (LC == RTLIB::UNKNOWN_LIBCALL || !LibcallName)
186-
reportFatalInternalError("unsupported library call operation");
185+
if (LC == RTLIB::UNKNOWN_LIBCALL || !LibcallName) {
186+
reportFatalInternalError("unsupported library call operation: "
187+
"libcall " + Twine(LC));
188+
}
187189

188190
SDValue Callee =
189191
DAG.getExternalSymbol(LibcallName, getPointerTy(DAG.getDataLayout()));

0 commit comments

Comments
 (0)