Skip to content

Commit fac24c7

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 f766252 commit fac24c7

30 files changed

+435
-332
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: 93 additions & 67 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
@@ -363,6 +365,9 @@ def MIPS16_RET_DF : RuntimeLibcall;
363365
def MIPS16_RET_SC : RuntimeLibcall;
364366
def MIPS16_RET_SF : RuntimeLibcall;
365367

368+
// Create libcall impls for `long double` and `_Float128`. See also `_ld128`
369+
// impls defined at `LibmF128AsLongDoubleLibcalls`.
370+
366371
// Produce libcall impls for all float types. If provided, `rtbasename` should
367372
// contain an `X` that will be replaced with the `f`/`l`/`fX` suffix (if not
368373
// provided, it is appended to the def name).
@@ -376,7 +381,7 @@ multiclass LibmLibcallImpls<string libcall_basename = !toupper(NAME),
376381
!subst("X", "", rtbasename)>;
377382
def NAME#"_f128"
378383
: RuntimeLibcallImpl<!cast<RuntimeLibcall>(libcall_basename#"_F128"),
379-
!subst("X", "l", rtbasename)>;
384+
!subst("X", "f128", rtbasename)>;
380385
def NAME#"_ppcf128"
381386
: RuntimeLibcallImpl<!cast<RuntimeLibcall>(libcall_basename#"_PPCF128"),
382387
!subst("X", "l", rtbasename)>;
@@ -385,6 +390,14 @@ multiclass LibmLibcallImpls<string libcall_basename = !toupper(NAME),
385390
!subst("X", "l", rtbasename)>;
386391
}
387392

393+
multiclass LibmF128AsLongDoubleImpls<string libcall_basename = !toupper(NAME),
394+
string rtbasename =
395+
!strconcat(NAME, "X")> {
396+
def NAME#"_ld128"
397+
: RuntimeLibcallImpl<!cast<RuntimeLibcall>(libcall_basename#"_F128"),
398+
!subst("X", "l", rtbasename)>;
399+
}
400+
388401
// AArch64 calls
389402
def SC_MEMCPY : RuntimeLibcall;
390403
def SC_MEMMOVE : RuntimeLibcall;
@@ -806,60 +819,65 @@ def __riscv_flush_icache : RuntimeLibcallImpl<RISCV_FLUSH_ICACHE>;
806819
// F128 libm Runtime Libcalls
807820
//===----------------------------------------------------------------------===//
808821

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

855-
defset list<RuntimeLibcallImpl> LibmF128FiniteLibcalls = {
856-
def __logf128_finite : RuntimeLibcallImpl<LOG_FINITE_F128>;
857-
def __log2f128_finite : RuntimeLibcallImpl<LOG2_FINITE_F128>;
858-
def __log10f128_finite : RuntimeLibcallImpl<LOG10_FINITE_F128>;
859-
def __expf128_finite : RuntimeLibcallImpl<EXP_FINITE_F128>;
860-
def __exp2f128_finite : RuntimeLibcallImpl<EXP2_FINITE_F128>;
861-
def __exp10f128_finite : RuntimeLibcallImpl<EXP10_FINITE_F128>;
862-
def __powf128_finite : RuntimeLibcallImpl<POW_FINITE_F128>;
869+
defset list<RuntimeLibcallImpl> LibmF128AsLongDoubleFiniteLibcalls = {
870+
defm __log_finite : LibmF128AsLongDoubleImpls<"LOG_FINITE", "__logX_finite">;
871+
defm __log2_finite
872+
: LibmF128AsLongDoubleImpls<"LOG2_FINITE", "__log2X_finite">;
873+
defm __log10_finite
874+
: LibmF128AsLongDoubleImpls<"LOG10_FINITE", "__log10X_finite">;
875+
defm __exp_finite : LibmF128AsLongDoubleImpls<"EXP_FINITE", "__expX_finite">;
876+
defm __exp2_finite
877+
: LibmF128AsLongDoubleImpls<"EXP2_FINITE", "__exp2X_finite">;
878+
defm __exp10_finite
879+
: LibmF128AsLongDoubleImpls<"EXP10_FINITE", "__exp10X_finite">;
880+
defm __pow_finite : LibmF128AsLongDoubleImpls<"POW_FINITE", "__powX_finite">;
863881
}
864882

865883
//===----------------------------------------------------------------------===//
@@ -893,10 +911,6 @@ defvar DefaultRuntimeLibcallImpls_ppcf128 =
893911
!filter(entry, AllDefaultRuntimeLibcallImpls,
894912
!match(!cast<string>(entry.Provides), "PPCF128"));
895913

896-
defvar DefaultRuntimeLibcallImpls_f128 =
897-
!filter(entry, AllDefaultRuntimeLibcallImpls,
898-
!match(!cast<string>(entry.Provides), "_F128"));
899-
900914
defvar DefaultRuntimeLibcallImpls =
901915
!listremove(
902916
!listremove(
@@ -1690,7 +1704,7 @@ def NVPTXSystemLibrary : SystemRuntimeLibrary<isNVPTX, (add)>;
16901704
//===----------------------------------------------------------------------===//
16911705

16921706
// For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf".
1693-
defset list<RuntimeLibcallImpl> PPCRuntimeLibcalls = {
1707+
defset list<RuntimeLibcallImpl> PPCOverriddenRuntimeLibcalls = {
16941708
def __addkf3 : RuntimeLibcallImpl<ADD_F128>;
16951709
def __subkf3 : RuntimeLibcallImpl<SUB_F128>;
16961710
def __mulkf3 : RuntimeLibcallImpl<MUL_F128>;
@@ -1734,7 +1748,17 @@ defset list<RuntimeLibcallImpl> PPC32AIXCallList = {
17341748
def ___bzero : RuntimeLibcallImpl<BZERO>;
17351749
}
17361750

1737-
defvar PPCOverrides = !foreach(entry, PPCRuntimeLibcalls, entry.Provides);
1751+
// List of overriden libcalls as strings, `["ADD_F128", "SUB_F128", ...]`
1752+
defvar PPCOverriddenNames = !foreach(entry, PPCOverriddenRuntimeLibcalls,
1753+
!cast<string>(entry.Provides));
1754+
1755+
// Default libcalls except for those that appear in `PPCOverrideNames`
1756+
defvar PPCNonOverriddenImpls = !filter(
1757+
default_entry, DefaultRuntimeLibcallImpls,
1758+
// `!contains` does not exist, `not->empty->filter` is a slightly hacky way
1759+
!not(!empty(
1760+
!filter(overridden, PPCOverriddenNames,
1761+
!eq(overridden, !cast<string>(default_entry.Provides))))));
17381762

17391763
def isPPC : RuntimeLibcallPredicate<"TT.isPPC()">;
17401764
def isPPC32 : RuntimeLibcallPredicate<"TT.isPPC32()">;
@@ -1747,20 +1771,22 @@ def isPPC64_AIX : RuntimeLibcallPredicate<"(TT.isPPC64() && TT.isOSAIX())">;
17471771
def AIX32Calls : LibcallImpls<(add PPC32AIXCallList), isPPC32_AIX>;
17481772
def AIX64Calls : LibcallImpls<(add PPC64AIXCallList), isPPC64_AIX>;
17491773

1774+
// Replace overridden values, adjust mem* symbols, add ppc_f128<->f128
1775+
// conversions.
1776+
defvar PPCDefaultRuntimeLibcallImpls = (add
1777+
(sub DefaultRuntimeLibcallImpls, PPCNonOverriddenImpls, memcpy),
1778+
PPCOverriddenRuntimeLibcalls, __extendkftf2, __trunctfkf2,
1779+
DefaultRuntimeLibcallImpls_ppcf128, AIX32Calls, AIX64Calls);
1780+
17501781
// FIXME: Current emission behavior with multiple implementations is
17511782
// janky. We need to filter out the conflicting cases with different
17521783
// f128 names, and then add the overrides. We should switch to
17531784
// explicitly adding subsets of the default calls.
17541785
def PPCSystemLibrary
17551786
: SystemRuntimeLibrary<isPPC,
1756-
(add PPCRuntimeLibcalls,
1757-
(sub DefaultRuntimeLibcallImpls, memcpy,
1758-
DefaultRuntimeLibcallImpls_f128),
1759-
__extendkftf2, __trunctfkf2,
1760-
DefaultRuntimeLibcallImpls_ppcf128,
1761-
LibmF128Libcalls, AIX32Calls, AIX64Calls,
1762-
AvailableIf<memcpy, isNotAIX>,
1763-
LibcallImpls<(add Int128RTLibcalls), isPPC64>)>;
1787+
(add PPCDefaultRuntimeLibcallImpls,
1788+
AvailableIf<memcpy, isNotAIX>,
1789+
LibcallImpls<(add Int128RTLibcalls), isPPC64>)>;
17641790

17651791
//===----------------------------------------------------------------------===//
17661792
// RISCV Runtime Libcalls

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: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,11 @@ 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 " +
188+
Twine(LC));
189+
}
187190

188191
SDValue Callee =
189192
DAG.getExternalSymbol(LibcallName, getPointerTy(DAG.getDataLayout()));

0 commit comments

Comments
 (0)