https://github.com/tgross35 updated 
https://github.com/llvm/llvm-project/pull/76558

>From 9089a966f2107a2dfcad86fec746e9f2bd8a105b Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgr...@umich.edu>
Date: Fri, 11 Aug 2023 22:16:01 -0400
Subject: [PATCH 1/5] [IR] Add a test for `f128` libcall lowering (NFC)

`f128` intrinsic functions sometimes lower to `long double` library
calls when they instead need to be `f128` versions. Add a test
demonstrating current behavior.
---
 .../CodeGen/Generic/f128-math-lowering.ll     | 328 ++++++++++++++++++
 1 file changed, 328 insertions(+)
 create mode 100644 llvm/test/CodeGen/Generic/f128-math-lowering.ll

diff --git a/llvm/test/CodeGen/Generic/f128-math-lowering.ll 
b/llvm/test/CodeGen/Generic/f128-math-lowering.ll
new file mode 100644
index 0000000000000..dfbd1eaeda109
--- /dev/null
+++ b/llvm/test/CodeGen/Generic/f128-math-lowering.ll
@@ -0,0 +1,328 @@
+; RUN: llc < %s -mtriple=aarch64-unknown-none -verify-machineinstrs | 
FileCheck %s --check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=i686-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=riscv32 -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=s390x-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-S390X
+; RUN: llc < %s -mtriple=x86_64-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs | 
FileCheck %s --check-prefix=CHECK-NOTLD
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-musl -verify-machineinstrs | 
FileCheck %s --check-prefix=CHECK-USELD
+;
+; REQUIRES: aarch64-registered-target
+; REQUIRES: riscv-registered-target
+; REQUIRES: systemz-registered-target
+; REQUIRES: x86-registered-target
+;
+; Verify that fp128 intrinsics only lower to `long double` calls (e.g. `sinl`)
+; on platforms where `f128` and `long double` have the same layout, and
+; otherwise lower to `f128` versions (e.g. `sinf128`).
+;
+; Targets include:
+; * x86, x64 (80-bit long double)
+; * aarch64 (long double == f128)
+; * riscv32 (long double == f64)
+; * s390x (long double == f128, hardware support)
+; * A couple assorted environments for x86
+;
+; FIXME: only targets where long double is `f128` should be using `USELD`, all
+; others need to be NOTLD. PowerPC should be added but it currently emits an
+; interesting blend of both (e.g. `acosl` but `ceilf128`).
+
+define fp128 @test_acosf128(fp128 %a) {
+; CHECK-LABEL:      test_acosf128:
+; CHECK-NOTLD:      acosf128
+; CHECK-USELD:      acosl
+; CHECK-S390X:      acosl
+start:
+  %0 = tail call fp128 @llvm.acos.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_asinf128(fp128 %a) {
+; CHECK-LABEL:      test_asinf128:
+; CHECK-NOTLD:      asinf128
+; CHECK-USELD:      asinl
+; CHECK-S390X:      asinl
+start:
+  %0 = tail call fp128 @llvm.asin.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_atanf128(fp128 %a) {
+; CHECK-LABEL:      test_atanf128:
+; CHECK-NOTLD:      atanf128
+; CHECK-USELD:      atanl
+; CHECK-S390X:      atanl
+start:
+  %0 = tail call fp128 @llvm.atan.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_ceilf128(fp128 %a) {
+; CHECK-LABEL:      test_ceilf128:
+; CHECK-NOTLD:      ceilf128
+; CHECK-USELD:      ceill
+; CHECK-S390X:      ceill
+start:
+  %0 = tail call fp128 @llvm.ceil.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_copysignf128(fp128 %a, fp128 %b) {
+; copysign should always get lowered to assembly
+; CHECK-LABEL:      test_copysignf128:
+; CHECK-NOT:        copysignl
+; CHECK-NOT:        copysignf128
+start:
+  %0 = tail call fp128 @llvm.copysign.f128(fp128 %a, fp128 %b)
+  ret fp128 %0
+}
+
+define fp128 @test_cosf128(fp128 %a) {
+; CHECK-LABEL:      test_cosf128:
+; CHECK-NOTLD:      cosf128
+; CHECK-USELD:      cosl
+; CHECK-S390X:      cosl
+start:
+  %0 = tail call fp128 @llvm.cos.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_exp10f128(fp128 %a) {
+; CHECK-LABEL:      test_exp2f128:
+; CHECK-NOTLD:      exp10f128
+; CHECK-USELD:      exp10l
+; CHECK-S390X:      exp10l
+start:
+  %0 = tail call fp128 @llvm.exp10.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_exp2f128(fp128 %a) {
+; CHECK-LABEL:      test_exp2f128:
+; CHECK-NOTLD:      exp2f128
+; CHECK-USELD:      exp2l
+; CHECK-S390X:      exp2l
+start:
+  %0 = tail call fp128 @llvm.exp2.f128(fp128 %a)
+  ret fp128 %0
+}
+
+
+define fp128 @test_expf128(fp128 %a) {
+; CHECK-LABEL:      test_expf128:
+; CHECK-NOTLD:      expf128
+; CHECK-USELD:      expl
+; CHECK-S390X:      expl
+start:
+  %0 = tail call fp128 @llvm.exp.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_fabsf128(fp128 %a) {
+; fabs should always get lowered to assembly
+; CHECK-LABEL:      test_fabsf128:
+; CHECK-NOT:        fabsl
+; CHECK-NOT:        fabsf128
+start:
+  %0 = tail call fp128 @llvm.fabs.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_floorf128(fp128 %a) {
+; CHECK-LABEL:      test_floorf128:
+; CHECK-NOTLD:      floorf128
+; CHECK-USELD:      floorl
+; CHECK-S390X:      floorl
+start:
+  %0 = tail call fp128 @llvm.floor.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_fmaf128(fp128 %a, fp128 %b, fp128 %c) {
+; CHECK-LABEL:      test_fmaf128:
+; CHECK-NOTLD:      fmaf128
+; CHECK-USELD:      fmal
+; CHECK-S390X:      fmal
+start:
+  %0 = tail call fp128 @llvm.fma.f128(fp128 %a, fp128 %b, fp128 %c)
+  ret fp128 %0
+}
+
+define { fp128, i32 } @test_frexpf128(fp128 %a) {
+; CHECK-LABEL:      test_frexpf128:
+; CHECK-NOTLD:      frexpf128
+; CHECK-USELD:      frexpl
+; CHECK-S390X:      frexpl
+start:
+  %0 = tail call { fp128, i32 } @llvm.frexp.f128(fp128 %a)
+  ret { fp128, i32 } %0
+}
+
+define fp128 @test_ldexpf128(fp128 %a, i32 %b) {
+; CHECK-LABEL:      test_ldexpf128:
+; CHECK-NOTLD:      ldexpf128
+; CHECK-USELD:      ldexpl
+; CHECK-S390X:      ldexpl
+start:
+  %0 = tail call fp128 @llvm.ldexp.f128(fp128 %a, i32 %b)
+  ret fp128 %0
+}
+
+define i64 @test_llrintf128(fp128 %a) {
+; CHECK-LABEL:      test_llrintf128:
+; CHECK-NOTLD:      llrintf128
+; CHECK-USELD:      llrintl
+; CHECK-S390X:      llrintl
+start:
+  %0 = tail call i64 @llvm.llrint.f128(fp128 %a)
+  ret i64 %0
+}
+
+define i64 @test_llroundf128(fp128 %a) {
+; CHECK-LABEL:      test_llroundf128:
+; CHECK-NOTLD:      llroundf128
+; CHECK-USELD:      llroundl
+; CHECK-S390X:      llroundl
+start:
+  %0 = tail call i64 @llvm.llround.i64.f128(fp128 %a)
+  ret i64 %0
+}
+
+define fp128 @test_log10f128(fp128 %a) {
+; CHECK-LABEL:      test_log10f128:
+; CHECK-NOTLD:      log10f128
+; CHECK-USELD:      log10l
+; CHECK-S390X:      log10l
+start:
+  %0 = tail call fp128 @llvm.log10.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_log2f128(fp128 %a) {
+; CHECK-LABEL:      test_log2f128:
+; CHECK-NOTLD:      log2f128
+; CHECK-USELD:      log2l
+; CHECK-S390X:      log2l
+start:
+  %0 = tail call fp128 @llvm.log2.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_logf128(fp128 %a) {
+; CHECK-LABEL:      test_logf128:
+; CHECK-NOTLD:      logf128
+; CHECK-USELD:      logl
+; CHECK-S390X:      logl
+start:
+  %0 = tail call fp128 @llvm.log.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define i64 @test_lrintf128(fp128 %a) {
+; CHECK-LABEL:      test_exp2f128:
+; CHECK-NOTLD:      lrintf128
+; CHECK-USELD:      lrintl
+; CHECK-S390X:      lrintl
+start:
+  %0 = tail call i64 @llvm.lrint.f128(fp128 %a)
+  ret i64 %0
+}
+
+define i64 @test_lroundf128(fp128 %a) {
+; CHECK-LABEL:      test_lroundf128:
+; CHECK-NOTLD:      lroundf128
+; CHECK-USELD:      lroundl
+; CHECK-S390X:      lroundl
+start:
+  %0 = tail call i64 @llvm.lround.i64.f128(fp128 %a)
+  ret i64 %0
+}
+
+define fp128 @test_nearbyintf128(fp128 %a) {
+; CHECK-LABEL:      test_nearbyintf128:
+; CHECK-NOTLD:      nearbyintf128
+; CHECK-USELD:      nearbyintl
+; CHECK-S390X:      nearbyintl
+start:
+  %0 = tail call fp128 @llvm.nearbyint.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_powf128(fp128 %a, fp128 %b) {
+; CHECK-LABEL:      test_powf128:
+; CHECK-NOTLD:      powf128
+; CHECK-USELD:      powl
+; CHECK-S390X:      powl
+start:
+  %0 = tail call fp128 @llvm.pow.f128(fp128 %a, fp128 %b)
+  ret fp128 %0
+}
+
+define fp128 @test_rintf128(fp128 %a) {
+; CHECK-LABEL:      test_rintf128:
+; CHECK-NOTLD:      rintf128
+; CHECK-USELD:      rintl
+; CHECK-S390X:      fixbr {{%.*}}, 0, {{%.*}}
+start:
+  %0 = tail call fp128 @llvm.rint.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_roundevenf128(fp128 %a) {
+; CHECK-LABEL:      test_roundevenf128:
+; CHECK-NOTLD:      roundevenf128
+; CHECK-USELD:      roundevenl
+; CHECK-S390X:      roundevenl
+start:
+  %0 = tail call fp128 @llvm.roundeven.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_roundf128(fp128 %a) {
+; CHECK-LABEL:      test_roundf128:
+; CHECK-NOTLD:      roundf128
+; CHECK-USELD:      roundl
+; CHECK-S390X:      roundl
+start:
+  %0 = tail call fp128 @llvm.round.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_sinf128(fp128 %a) {
+; CHECK-LABEL:      test_sinf128:
+; CHECK-NOTLD:      sinf128
+; CHECK-USELD:      sinl
+; CHECK-S390X:      sinl
+start:
+  %0 = tail call fp128 @llvm.sin.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_sqrtf128(fp128 %a) {
+; CHECK-LABEL:      test_sqrtf128:
+; CHECK-NOTLD:      sqrtf128
+; CHECK-USELD:      sqrtl
+; CHECK-S390X:      sqxbr {{%.*}}, {{%.*}}
+start:
+  %0 = tail call fp128 @llvm.sqrt.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_tanf128(fp128 %a) {
+; CHECK-LABEL:      test_tanf128:
+; CHECK-NOTLD:      tanf128
+; CHECK-USELD:      tanl
+; CHECK-S390X:      tanl
+start:
+  %0 = tail call fp128 @llvm.tan.f128(fp128 %a)
+  ret fp128 %0
+}
+
+define fp128 @test_truncf128(fp128 %a) {
+; CHECK-LABEL:      test_truncf128:
+; CHECK-NOTLD:      truncf128
+; CHECK-USELD:      truncl
+; CHECK-S390X:      truncl
+start:
+  %0 = tail call fp128 @llvm.trunc.f128(fp128 %a)
+  ret fp128 %0
+}

>From 823a4ddf766d20aafbea1fef7d82eb4a27d834b1 Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgr...@umich.edu>
Date: Thu, 28 Dec 2023 04:01:22 -0500
Subject: [PATCH 2/5] [IR] Change `fp128` lowering to use `f128` functions by
 default

Switch from emitting long double functions to using `f128`-specific functions.

Fixes https://github.com/llvm/llvm-project/issues/44744.
---
 llvm/include/llvm/IR/RuntimeLibcalls.def      | 98 +++++++++----------
 llvm/lib/IR/RuntimeLibcalls.cpp               | 94 +++++++++---------
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   | 26 -----
 .../CodeGen/Generic/f128-math-lowering.ll     | 11 ++-
 4 files changed, 103 insertions(+), 126 deletions(-)

diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.def 
b/llvm/include/llvm/IR/RuntimeLibcalls.def
index c6ac341d71a20..515b484cab343 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.def
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.def
@@ -110,12 +110,12 @@ HANDLE_LIBCALL(DIV_PPCF128, "__gcc_qdiv")
 HANDLE_LIBCALL(REM_F32, "fmodf")
 HANDLE_LIBCALL(REM_F64, "fmod")
 HANDLE_LIBCALL(REM_F80, "fmodl")
-HANDLE_LIBCALL(REM_F128, "fmodl")
+HANDLE_LIBCALL(REM_F128, "fmodf128")
 HANDLE_LIBCALL(REM_PPCF128, "fmodl")
 HANDLE_LIBCALL(FMA_F32, "fmaf")
 HANDLE_LIBCALL(FMA_F64, "fma")
 HANDLE_LIBCALL(FMA_F80, "fmal")
-HANDLE_LIBCALL(FMA_F128, "fmal")
+HANDLE_LIBCALL(FMA_F128, "fmaf128")
 HANDLE_LIBCALL(FMA_PPCF128, "fmal")
 HANDLE_LIBCALL(POWI_F32, "__powisf2")
 HANDLE_LIBCALL(POWI_F64, "__powidf2")
@@ -125,117 +125,117 @@ HANDLE_LIBCALL(POWI_PPCF128, "__powitf2")
 HANDLE_LIBCALL(SQRT_F32, "sqrtf")
 HANDLE_LIBCALL(SQRT_F64, "sqrt")
 HANDLE_LIBCALL(SQRT_F80, "sqrtl")
-HANDLE_LIBCALL(SQRT_F128, "sqrtl")
+HANDLE_LIBCALL(SQRT_F128, "sqrtf128")
 HANDLE_LIBCALL(SQRT_PPCF128, "sqrtl")
 HANDLE_LIBCALL(CBRT_F32, "cbrtf")
 HANDLE_LIBCALL(CBRT_F64, "cbrt")
 HANDLE_LIBCALL(CBRT_F80, "cbrtl")
-HANDLE_LIBCALL(CBRT_F128, "cbrtl")
+HANDLE_LIBCALL(CBRT_F128, "cbrtf128")
 HANDLE_LIBCALL(CBRT_PPCF128, "cbrtl")
 HANDLE_LIBCALL(LOG_F32, "logf")
 HANDLE_LIBCALL(LOG_F64, "log")
 HANDLE_LIBCALL(LOG_F80, "logl")
-HANDLE_LIBCALL(LOG_F128, "logl")
+HANDLE_LIBCALL(LOG_F128, "logf128")
 HANDLE_LIBCALL(LOG_PPCF128, "logl")
 HANDLE_LIBCALL(LOG_FINITE_F32, "__logf_finite")
 HANDLE_LIBCALL(LOG_FINITE_F64, "__log_finite")
 HANDLE_LIBCALL(LOG_FINITE_F80, "__logl_finite")
-HANDLE_LIBCALL(LOG_FINITE_F128, "__logl_finite")
+HANDLE_LIBCALL(LOG_FINITE_F128, "__logf128_finite")
 HANDLE_LIBCALL(LOG_FINITE_PPCF128, "__logl_finite")
 HANDLE_LIBCALL(LOG2_F32, "log2f")
 HANDLE_LIBCALL(LOG2_F64, "log2")
 HANDLE_LIBCALL(LOG2_F80, "log2l")
-HANDLE_LIBCALL(LOG2_F128, "log2l")
+HANDLE_LIBCALL(LOG2_F128, "log2f128")
 HANDLE_LIBCALL(LOG2_PPCF128, "log2l")
 HANDLE_LIBCALL(LOG2_FINITE_F32, "__log2f_finite")
 HANDLE_LIBCALL(LOG2_FINITE_F64, "__log2_finite")
 HANDLE_LIBCALL(LOG2_FINITE_F80, "__log2l_finite")
-HANDLE_LIBCALL(LOG2_FINITE_F128, "__log2l_finite")
+HANDLE_LIBCALL(LOG2_FINITE_F128, "__log2f128_finite")
 HANDLE_LIBCALL(LOG2_FINITE_PPCF128, "__log2l_finite")
 HANDLE_LIBCALL(LOG10_F32, "log10f")
 HANDLE_LIBCALL(LOG10_F64, "log10")
 HANDLE_LIBCALL(LOG10_F80, "log10l")
-HANDLE_LIBCALL(LOG10_F128, "log10l")
+HANDLE_LIBCALL(LOG10_F128, "log10f128")
 HANDLE_LIBCALL(LOG10_PPCF128, "log10l")
 HANDLE_LIBCALL(LOG10_FINITE_F32, "__log10f_finite")
 HANDLE_LIBCALL(LOG10_FINITE_F64, "__log10_finite")
 HANDLE_LIBCALL(LOG10_FINITE_F80, "__log10l_finite")
-HANDLE_LIBCALL(LOG10_FINITE_F128, "__log10l_finite")
+HANDLE_LIBCALL(LOG10_FINITE_F128, "__log10f128_finite")
 HANDLE_LIBCALL(LOG10_FINITE_PPCF128, "__log10l_finite")
 HANDLE_LIBCALL(EXP_F32, "expf")
 HANDLE_LIBCALL(EXP_F64, "exp")
 HANDLE_LIBCALL(EXP_F80, "expl")
-HANDLE_LIBCALL(EXP_F128, "expl")
+HANDLE_LIBCALL(EXP_F128, "expf128")
 HANDLE_LIBCALL(EXP_PPCF128, "expl")
 HANDLE_LIBCALL(EXP_FINITE_F32, "__expf_finite")
 HANDLE_LIBCALL(EXP_FINITE_F64, "__exp_finite")
 HANDLE_LIBCALL(EXP_FINITE_F80, "__expl_finite")
-HANDLE_LIBCALL(EXP_FINITE_F128, "__expl_finite")
+HANDLE_LIBCALL(EXP_FINITE_F128, "__expf128_finite")
 HANDLE_LIBCALL(EXP_FINITE_PPCF128, "__expl_finite")
 HANDLE_LIBCALL(EXP2_F32, "exp2f")
 HANDLE_LIBCALL(EXP2_F64, "exp2")
 HANDLE_LIBCALL(EXP2_F80, "exp2l")
-HANDLE_LIBCALL(EXP2_F128, "exp2l")
+HANDLE_LIBCALL(EXP2_F128, "exp2f128")
 HANDLE_LIBCALL(EXP2_PPCF128, "exp2l")
 HANDLE_LIBCALL(EXP2_FINITE_F32, "__exp2f_finite")
 HANDLE_LIBCALL(EXP2_FINITE_F64, "__exp2_finite")
 HANDLE_LIBCALL(EXP2_FINITE_F80, "__exp2l_finite")
-HANDLE_LIBCALL(EXP2_FINITE_F128, "__exp2l_finite")
+HANDLE_LIBCALL(EXP2_FINITE_F128, "__exp2f128_finite")
 HANDLE_LIBCALL(EXP2_FINITE_PPCF128, "__exp2l_finite")
 HANDLE_LIBCALL(EXP10_F32, "exp10f")
 HANDLE_LIBCALL(EXP10_F64, "exp10")
 HANDLE_LIBCALL(EXP10_F80, "exp10l")
-HANDLE_LIBCALL(EXP10_F128, "exp10l")
+HANDLE_LIBCALL(EXP10_F128, "exp10f128")
 HANDLE_LIBCALL(EXP10_PPCF128, "exp10l")
 HANDLE_LIBCALL(SIN_F32, "sinf")
 HANDLE_LIBCALL(SIN_F64, "sin")
 HANDLE_LIBCALL(SIN_F80, "sinl")
-HANDLE_LIBCALL(SIN_F128, "sinl")
+HANDLE_LIBCALL(SIN_F128, "sinf128")
 HANDLE_LIBCALL(SIN_PPCF128, "sinl")
 HANDLE_LIBCALL(COS_F32, "cosf")
 HANDLE_LIBCALL(COS_F64, "cos")
 HANDLE_LIBCALL(COS_F80, "cosl")
-HANDLE_LIBCALL(COS_F128, "cosl")
+HANDLE_LIBCALL(COS_F128, "cosf128")
 HANDLE_LIBCALL(COS_PPCF128, "cosl")
 HANDLE_LIBCALL(TAN_F32, "tanf")
 HANDLE_LIBCALL(TAN_F64, "tan")
 HANDLE_LIBCALL(TAN_F80, "tanl")
-HANDLE_LIBCALL(TAN_F128,"tanl")
+HANDLE_LIBCALL(TAN_F128,"tanf128")
 HANDLE_LIBCALL(TAN_PPCF128, "tanl")
 HANDLE_LIBCALL(SINH_F32, "sinhf")
 HANDLE_LIBCALL(SINH_F64, "sinh")
 HANDLE_LIBCALL(SINH_F80, "sinhl")
-HANDLE_LIBCALL(SINH_F128, "sinhl")
+HANDLE_LIBCALL(SINH_F128, "sinhf128")
 HANDLE_LIBCALL(SINH_PPCF128, "sinhl")
 HANDLE_LIBCALL(COSH_F32, "coshf")
 HANDLE_LIBCALL(COSH_F64, "cosh")
 HANDLE_LIBCALL(COSH_F80, "coshl")
-HANDLE_LIBCALL(COSH_F128, "coshl")
+HANDLE_LIBCALL(COSH_F128, "coshf128")
 HANDLE_LIBCALL(COSH_PPCF128, "coshl")
 HANDLE_LIBCALL(TANH_F32, "tanhf")
 HANDLE_LIBCALL(TANH_F64, "tanh")
 HANDLE_LIBCALL(TANH_F80, "tanhl")
-HANDLE_LIBCALL(TANH_F128,"tanhl")
+HANDLE_LIBCALL(TANH_F128,"tanhf128")
 HANDLE_LIBCALL(TANH_PPCF128, "tanhl")
 HANDLE_LIBCALL(ASIN_F32, "asinf")
 HANDLE_LIBCALL(ASIN_F64, "asin")
 HANDLE_LIBCALL(ASIN_F80, "asinl")
-HANDLE_LIBCALL(ASIN_F128, "asinl")
+HANDLE_LIBCALL(ASIN_F128, "asinf128")
 HANDLE_LIBCALL(ASIN_PPCF128, "asinl")
 HANDLE_LIBCALL(ACOS_F32, "acosf")
 HANDLE_LIBCALL(ACOS_F64, "acos")
 HANDLE_LIBCALL(ACOS_F80, "acosl")
-HANDLE_LIBCALL(ACOS_F128, "acosl")
+HANDLE_LIBCALL(ACOS_F128, "acosf128")
 HANDLE_LIBCALL(ACOS_PPCF128, "acosl")
 HANDLE_LIBCALL(ATAN_F32, "atanf")
 HANDLE_LIBCALL(ATAN_F64, "atan")
 HANDLE_LIBCALL(ATAN_F80, "atanl")
-HANDLE_LIBCALL(ATAN_F128,"atanl")
+HANDLE_LIBCALL(ATAN_F128,"atanf128")
 HANDLE_LIBCALL(ATAN_PPCF128, "atanl")
 HANDLE_LIBCALL(ATAN2_F32, "atan2f")
 HANDLE_LIBCALL(ATAN2_F64, "atan2")
 HANDLE_LIBCALL(ATAN2_F80, "atan2l")
-HANDLE_LIBCALL(ATAN2_F128,"atan2l")
+HANDLE_LIBCALL(ATAN2_F128,"atan2f128")
 HANDLE_LIBCALL(ATAN2_PPCF128, "atan2l")
 HANDLE_LIBCALL(SINCOS_F32, nullptr)
 HANDLE_LIBCALL(SINCOS_F64, nullptr)
@@ -247,122 +247,122 @@ HANDLE_LIBCALL(SINCOS_STRET_F64, nullptr)
 HANDLE_LIBCALL(POW_F32, "powf")
 HANDLE_LIBCALL(POW_F64, "pow")
 HANDLE_LIBCALL(POW_F80, "powl")
-HANDLE_LIBCALL(POW_F128, "powl")
+HANDLE_LIBCALL(POW_F128, "powf128")
 HANDLE_LIBCALL(POW_PPCF128, "powl")
 HANDLE_LIBCALL(POW_FINITE_F32, "__powf_finite")
 HANDLE_LIBCALL(POW_FINITE_F64, "__pow_finite")
 HANDLE_LIBCALL(POW_FINITE_F80, "__powl_finite")
-HANDLE_LIBCALL(POW_FINITE_F128, "__powl_finite")
+HANDLE_LIBCALL(POW_FINITE_F128, "__powf128_finite")
 HANDLE_LIBCALL(POW_FINITE_PPCF128, "__powl_finite")
 HANDLE_LIBCALL(CEIL_F32, "ceilf")
 HANDLE_LIBCALL(CEIL_F64, "ceil")
 HANDLE_LIBCALL(CEIL_F80, "ceill")
-HANDLE_LIBCALL(CEIL_F128, "ceill")
+HANDLE_LIBCALL(CEIL_F128, "ceilf128")
 HANDLE_LIBCALL(CEIL_PPCF128, "ceill")
 HANDLE_LIBCALL(TRUNC_F32, "truncf")
 HANDLE_LIBCALL(TRUNC_F64, "trunc")
 HANDLE_LIBCALL(TRUNC_F80, "truncl")
-HANDLE_LIBCALL(TRUNC_F128, "truncl")
+HANDLE_LIBCALL(TRUNC_F128, "truncf128")
 HANDLE_LIBCALL(TRUNC_PPCF128, "truncl")
 HANDLE_LIBCALL(RINT_F32, "rintf")
 HANDLE_LIBCALL(RINT_F64, "rint")
 HANDLE_LIBCALL(RINT_F80, "rintl")
-HANDLE_LIBCALL(RINT_F128, "rintl")
+HANDLE_LIBCALL(RINT_F128, "rintf128")
 HANDLE_LIBCALL(RINT_PPCF128, "rintl")
 HANDLE_LIBCALL(NEARBYINT_F32, "nearbyintf")
 HANDLE_LIBCALL(NEARBYINT_F64, "nearbyint")
 HANDLE_LIBCALL(NEARBYINT_F80, "nearbyintl")
-HANDLE_LIBCALL(NEARBYINT_F128, "nearbyintl")
+HANDLE_LIBCALL(NEARBYINT_F128, "nearbyintf128")
 HANDLE_LIBCALL(NEARBYINT_PPCF128, "nearbyintl")
 HANDLE_LIBCALL(ROUND_F32, "roundf")
 HANDLE_LIBCALL(ROUND_F64, "round")
 HANDLE_LIBCALL(ROUND_F80, "roundl")
-HANDLE_LIBCALL(ROUND_F128, "roundl")
+HANDLE_LIBCALL(ROUND_F128, "roundf128")
 HANDLE_LIBCALL(ROUND_PPCF128, "roundl")
 HANDLE_LIBCALL(ROUNDEVEN_F32, "roundevenf")
 HANDLE_LIBCALL(ROUNDEVEN_F64, "roundeven")
 HANDLE_LIBCALL(ROUNDEVEN_F80, "roundevenl")
-HANDLE_LIBCALL(ROUNDEVEN_F128, "roundevenl")
+HANDLE_LIBCALL(ROUNDEVEN_F128, "roundevenf128")
 HANDLE_LIBCALL(ROUNDEVEN_PPCF128, "roundevenl")
 HANDLE_LIBCALL(FLOOR_F32, "floorf")
 HANDLE_LIBCALL(FLOOR_F64, "floor")
 HANDLE_LIBCALL(FLOOR_F80, "floorl")
-HANDLE_LIBCALL(FLOOR_F128, "floorl")
+HANDLE_LIBCALL(FLOOR_F128, "floorf128")
 HANDLE_LIBCALL(FLOOR_PPCF128, "floorl")
 HANDLE_LIBCALL(COPYSIGN_F32, "copysignf")
 HANDLE_LIBCALL(COPYSIGN_F64, "copysign")
 HANDLE_LIBCALL(COPYSIGN_F80, "copysignl")
-HANDLE_LIBCALL(COPYSIGN_F128, "copysignl")
+HANDLE_LIBCALL(COPYSIGN_F128, "copysignf128")
 HANDLE_LIBCALL(COPYSIGN_PPCF128, "copysignl")
 HANDLE_LIBCALL(FMIN_F32, "fminf")
 HANDLE_LIBCALL(FMIN_F64, "fmin")
 HANDLE_LIBCALL(FMIN_F80, "fminl")
-HANDLE_LIBCALL(FMIN_F128, "fminl")
+HANDLE_LIBCALL(FMIN_F128, "fminf128")
 HANDLE_LIBCALL(FMIN_PPCF128, "fminl")
 HANDLE_LIBCALL(FMAX_F32, "fmaxf")
 HANDLE_LIBCALL(FMAX_F64, "fmax")
 HANDLE_LIBCALL(FMAX_F80, "fmaxl")
-HANDLE_LIBCALL(FMAX_F128, "fmaxl")
+HANDLE_LIBCALL(FMAX_F128, "fmaxf128")
 HANDLE_LIBCALL(FMAX_PPCF128, "fmaxl")
 HANDLE_LIBCALL(FMINIMUM_F32, "fminimumf")
 HANDLE_LIBCALL(FMINIMUM_F64, "fminimum")
 HANDLE_LIBCALL(FMINIMUM_F80, "fminimuml")
-HANDLE_LIBCALL(FMINIMUM_F128, "fminimuml")
+HANDLE_LIBCALL(FMINIMUM_F128, "fminimumf128")
 HANDLE_LIBCALL(FMINIMUM_PPCF128, "fminimuml")
 HANDLE_LIBCALL(FMAXIMUM_F32, "fmaximumf")
 HANDLE_LIBCALL(FMAXIMUM_F64, "fmaximum")
 HANDLE_LIBCALL(FMAXIMUM_F80, "fmaximuml")
-HANDLE_LIBCALL(FMAXIMUM_F128, "fmaximuml")
+HANDLE_LIBCALL(FMAXIMUM_F128, "fmaximumf128")
 HANDLE_LIBCALL(FMAXIMUM_PPCF128, "fmaximum_numl")
 HANDLE_LIBCALL(FMINIMUMNUM_F32, "fminimum_numf")
 HANDLE_LIBCALL(FMINIMUMNUM_F64, "fminimum_num")
 HANDLE_LIBCALL(FMINIMUMNUM_F80, "fminimum_numl")
-HANDLE_LIBCALL(FMINIMUMNUM_F128, "fminimum_numl")
+HANDLE_LIBCALL(FMINIMUMNUM_F128, "fminimum_numf128")
 HANDLE_LIBCALL(FMINIMUMNUM_PPCF128, "fminimum_numl")
 HANDLE_LIBCALL(FMAXIMUMNUM_F32, "fmaximum_numf")
 HANDLE_LIBCALL(FMAXIMUMNUM_F64, "fmaximum_num")
 HANDLE_LIBCALL(FMAXIMUMNUM_F80, "fmaximum_numl")
-HANDLE_LIBCALL(FMAXIMUMNUM_F128, "fmaximum_numl")
+HANDLE_LIBCALL(FMAXIMUMNUM_F128, "fmaximum_numf128")
 HANDLE_LIBCALL(FMAXIMUMNUM_PPCF128, "fmaximum_numl")
 HANDLE_LIBCALL(LROUND_F32, "lroundf")
 HANDLE_LIBCALL(LROUND_F64, "lround")
 HANDLE_LIBCALL(LROUND_F80, "lroundl")
-HANDLE_LIBCALL(LROUND_F128, "lroundl")
+HANDLE_LIBCALL(LROUND_F128, "lroundf128")
 HANDLE_LIBCALL(LROUND_PPCF128, "lroundl")
 HANDLE_LIBCALL(LLROUND_F32, "llroundf")
 HANDLE_LIBCALL(LLROUND_F64, "llround")
 HANDLE_LIBCALL(LLROUND_F80, "llroundl")
-HANDLE_LIBCALL(LLROUND_F128, "llroundl")
+HANDLE_LIBCALL(LLROUND_F128, "llroundf128")
 HANDLE_LIBCALL(LLROUND_PPCF128, "llroundl")
 HANDLE_LIBCALL(LRINT_F32, "lrintf")
 HANDLE_LIBCALL(LRINT_F64, "lrint")
 HANDLE_LIBCALL(LRINT_F80, "lrintl")
-HANDLE_LIBCALL(LRINT_F128, "lrintl")
+HANDLE_LIBCALL(LRINT_F128, "lrintf128")
 HANDLE_LIBCALL(LRINT_PPCF128, "lrintl")
 HANDLE_LIBCALL(LLRINT_F32, "llrintf")
 HANDLE_LIBCALL(LLRINT_F64, "llrint")
 HANDLE_LIBCALL(LLRINT_F80, "llrintl")
-HANDLE_LIBCALL(LLRINT_F128, "llrintl")
+HANDLE_LIBCALL(LLRINT_F128, "llrintf128")
 HANDLE_LIBCALL(LLRINT_PPCF128, "llrintl")
 HANDLE_LIBCALL(LDEXP_F32, "ldexpf")
 HANDLE_LIBCALL(LDEXP_F64, "ldexp")
 HANDLE_LIBCALL(LDEXP_F80, "ldexpl")
-HANDLE_LIBCALL(LDEXP_F128, "ldexpl")
+HANDLE_LIBCALL(LDEXP_F128, "ldexpf128")
 HANDLE_LIBCALL(LDEXP_PPCF128, "ldexpl")
 HANDLE_LIBCALL(FREXP_F32, "frexpf")
 HANDLE_LIBCALL(FREXP_F64, "frexp")
 HANDLE_LIBCALL(FREXP_F80, "frexpl")
-HANDLE_LIBCALL(FREXP_F128, "frexpl")
+HANDLE_LIBCALL(FREXP_F128, "frexpf128")
 HANDLE_LIBCALL(FREXP_PPCF128, "frexpl")
 HANDLE_LIBCALL(SINCOSPI_F32, "sincospif")
 HANDLE_LIBCALL(SINCOSPI_F64, "sincospi")
 HANDLE_LIBCALL(SINCOSPI_F80, "sincospil")
-HANDLE_LIBCALL(SINCOSPI_F128, "sincospil")
+HANDLE_LIBCALL(SINCOSPI_F128, "sincospif128")
 HANDLE_LIBCALL(SINCOSPI_PPCF128, "sincospil")
 HANDLE_LIBCALL(MODF_F32, "modff")
 HANDLE_LIBCALL(MODF_F64, "modf")
 HANDLE_LIBCALL(MODF_F80, "modfl")
-HANDLE_LIBCALL(MODF_F128, "modfl")
+HANDLE_LIBCALL(MODF_F128, "modff128")
 HANDLE_LIBCALL(MODF_PPCF128, "modfl")
 
 // Floating point environment
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index 1f94400f7c088..2e3b071c8f4bf 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -25,52 +25,53 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
   for (int LC = 0; LC < RTLIB::UNKNOWN_LIBCALL; ++LC)
     setLibcallCallingConv((RTLIB::Libcall)LC, CallingConv::C);
 
-  // Use the f128 variants of math functions on x86_64
-  if (TT.getArch() == Triple::ArchType::x86_64 && TT.isGNUEnvironment()) {
-    setLibcallName(RTLIB::REM_F128, "fmodf128");
-    setLibcallName(RTLIB::FMA_F128, "fmaf128");
-    setLibcallName(RTLIB::SQRT_F128, "sqrtf128");
-    setLibcallName(RTLIB::CBRT_F128, "cbrtf128");
-    setLibcallName(RTLIB::LOG_F128, "logf128");
-    setLibcallName(RTLIB::LOG_FINITE_F128, "__logf128_finite");
-    setLibcallName(RTLIB::LOG2_F128, "log2f128");
-    setLibcallName(RTLIB::LOG2_FINITE_F128, "__log2f128_finite");
-    setLibcallName(RTLIB::LOG10_F128, "log10f128");
-    setLibcallName(RTLIB::LOG10_FINITE_F128, "__log10f128_finite");
-    setLibcallName(RTLIB::EXP_F128, "expf128");
-    setLibcallName(RTLIB::EXP_FINITE_F128, "__expf128_finite");
-    setLibcallName(RTLIB::EXP2_F128, "exp2f128");
-    setLibcallName(RTLIB::EXP2_FINITE_F128, "__exp2f128_finite");
-    setLibcallName(RTLIB::EXP10_F128, "exp10f128");
-    setLibcallName(RTLIB::SIN_F128, "sinf128");
-    setLibcallName(RTLIB::COS_F128, "cosf128");
-    setLibcallName(RTLIB::TAN_F128, "tanf128");
-    setLibcallName(RTLIB::SINCOS_F128, "sincosf128");
-    setLibcallName(RTLIB::ASIN_F128, "asinf128");
-    setLibcallName(RTLIB::ACOS_F128, "acosf128");
-    setLibcallName(RTLIB::ATAN_F128, "atanf128");
-    setLibcallName(RTLIB::ATAN2_F128, "atan2f128");
-    setLibcallName(RTLIB::SINH_F128, "sinhf128");
-    setLibcallName(RTLIB::COSH_F128, "coshf128");
-    setLibcallName(RTLIB::TANH_F128, "tanhf128");
-    setLibcallName(RTLIB::POW_F128, "powf128");
-    setLibcallName(RTLIB::POW_FINITE_F128, "__powf128_finite");
-    setLibcallName(RTLIB::CEIL_F128, "ceilf128");
-    setLibcallName(RTLIB::TRUNC_F128, "truncf128");
-    setLibcallName(RTLIB::RINT_F128, "rintf128");
-    setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintf128");
-    setLibcallName(RTLIB::ROUND_F128, "roundf128");
-    setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenf128");
-    setLibcallName(RTLIB::FLOOR_F128, "floorf128");
-    setLibcallName(RTLIB::COPYSIGN_F128, "copysignf128");
-    setLibcallName(RTLIB::FMIN_F128, "fminf128");
-    setLibcallName(RTLIB::FMAX_F128, "fmaxf128");
-    setLibcallName(RTLIB::LROUND_F128, "lroundf128");
-    setLibcallName(RTLIB::LLROUND_F128, "llroundf128");
-    setLibcallName(RTLIB::LRINT_F128, "lrintf128");
-    setLibcallName(RTLIB::LLRINT_F128, "llrintf128");
-    setLibcallName(RTLIB::LDEXP_F128, "ldexpf128");
-    setLibcallName(RTLIB::FREXP_F128, "frexpf128");
+  // The long double version of library functions is more common than the
+  // f128-specific version. Use these if that is the long double type on the
+  // platform, or if the frontend specifies.
+  if (TT.isLongDoubleF128(""))  {
+    setLibcallName(RTLIB::ACOS_F128, "acosl");
+    setLibcallName(RTLIB::ASIN_F128, "asinl");
+    setLibcallName(RTLIB::ATAN2_F128,"atan2l");
+    setLibcallName(RTLIB::ATAN_F128,"atanl");
+    setLibcallName(RTLIB::CBRT_F128, "cbrtl");
+    setLibcallName(RTLIB::CEIL_F128, "ceill");
+    setLibcallName(RTLIB::COPYSIGN_F128, "copysignl");
+    setLibcallName(RTLIB::COSH_F128, "coshl");
+    setLibcallName(RTLIB::COS_F128, "cosl");
+    setLibcallName(RTLIB::EXP10_F128, "exp10l");
+    setLibcallName(RTLIB::EXP2_F128, "exp2l");
+    setLibcallName(RTLIB::EXP_F128, "expl");
+    setLibcallName(RTLIB::FLOOR_F128, "floorl");
+    setLibcallName(RTLIB::FMAXIMUMNUM_F128, "fmaximum_numl");
+    setLibcallName(RTLIB::FMAXIMUM_F128, "fmaximuml");
+    setLibcallName(RTLIB::FMAX_F128, "fmaxl");
+    setLibcallName(RTLIB::FMA_F128, "fmal");
+    setLibcallName(RTLIB::FMINIMUMNUM_F128, "fminimum_numl");
+    setLibcallName(RTLIB::FMINIMUM_F128, "fminimuml");
+    setLibcallName(RTLIB::FMIN_F128, "fminl");
+    setLibcallName(RTLIB::FREXP_F128, "frexpl");
+    setLibcallName(RTLIB::LDEXP_F128, "ldexpl");
+    setLibcallName(RTLIB::LLRINT_F128, "llrintl");
+    setLibcallName(RTLIB::LLROUND_F128, "llroundl");
+    setLibcallName(RTLIB::LOG10_F128, "log10l");
+    setLibcallName(RTLIB::LOG2_F128, "log2l");
+    setLibcallName(RTLIB::LOG_F128, "logl");
+    setLibcallName(RTLIB::LRINT_F128, "lrintl");
+    setLibcallName(RTLIB::LROUND_F128, "lroundl");
+    setLibcallName(RTLIB::MODF_F128, "modfl");
+    setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintl");
+    setLibcallName(RTLIB::POW_F128, "powl");
+    setLibcallName(RTLIB::REM_F128, "fmodl");
+    setLibcallName(RTLIB::RINT_F128, "rintl");
+    setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenl");
+    setLibcallName(RTLIB::ROUND_F128, "roundl");
+    setLibcallName(RTLIB::SINCOSPI_F128, "sincospil");
+    setLibcallName(RTLIB::SINH_F128, "sinhl");
+    setLibcallName(RTLIB::SIN_F128, "sinl");
+    setLibcallName(RTLIB::SQRT_F128, "sqrtl");
+    setLibcallName(RTLIB::TANH_F128,"tanhl");
+    setLibcallName(RTLIB::TAN_F128,"tanl");
+    setLibcallName(RTLIB::TRUNC_F128, "truncl");
   }
 
   // For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf".
@@ -177,7 +178,6 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
     setLibcallName(RTLIB::SINCOS_F32, "sincosf");
     setLibcallName(RTLIB::SINCOS_F64, "sincos");
     setLibcallName(RTLIB::SINCOS_F80, "sincosl");
-    setLibcallName(RTLIB::SINCOS_F128, "sincosl");
     setLibcallName(RTLIB::SINCOS_PPCF128, "sincosl");
   }
 
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp 
b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 91df5f467e59c..a17adfe3f0e59 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -1422,32 +1422,6 @@ PPCTargetLowering::PPCTargetLowering(const 
PPCTargetMachine &TM,
     setTargetDAGCombine({ISD::TRUNCATE, ISD::SETCC, ISD::SELECT_CC});
   }
 
-  setLibcallName(RTLIB::LOG_F128, "logf128");
-  setLibcallName(RTLIB::LOG2_F128, "log2f128");
-  setLibcallName(RTLIB::LOG10_F128, "log10f128");
-  setLibcallName(RTLIB::EXP_F128, "expf128");
-  setLibcallName(RTLIB::EXP2_F128, "exp2f128");
-  setLibcallName(RTLIB::SIN_F128, "sinf128");
-  setLibcallName(RTLIB::COS_F128, "cosf128");
-  setLibcallName(RTLIB::SINCOS_F128, "sincosf128");
-  setLibcallName(RTLIB::POW_F128, "powf128");
-  setLibcallName(RTLIB::FMIN_F128, "fminf128");
-  setLibcallName(RTLIB::FMAX_F128, "fmaxf128");
-  setLibcallName(RTLIB::REM_F128, "fmodf128");
-  setLibcallName(RTLIB::SQRT_F128, "sqrtf128");
-  setLibcallName(RTLIB::CEIL_F128, "ceilf128");
-  setLibcallName(RTLIB::FLOOR_F128, "floorf128");
-  setLibcallName(RTLIB::TRUNC_F128, "truncf128");
-  setLibcallName(RTLIB::ROUND_F128, "roundf128");
-  setLibcallName(RTLIB::LROUND_F128, "lroundf128");
-  setLibcallName(RTLIB::LLROUND_F128, "llroundf128");
-  setLibcallName(RTLIB::RINT_F128, "rintf128");
-  setLibcallName(RTLIB::LRINT_F128, "lrintf128");
-  setLibcallName(RTLIB::LLRINT_F128, "llrintf128");
-  setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintf128");
-  setLibcallName(RTLIB::FMA_F128, "fmaf128");
-  setLibcallName(RTLIB::FREXP_F128, "frexpf128");
-
   if (Subtarget.isAIXABI()) {
     setLibcallName(RTLIB::MEMCPY, isPPC64 ? "___memmove64" : "___memmove");
     setLibcallName(RTLIB::MEMMOVE, isPPC64 ? "___memmove64" : "___memmove");
diff --git a/llvm/test/CodeGen/Generic/f128-math-lowering.ll 
b/llvm/test/CodeGen/Generic/f128-math-lowering.ll
index dfbd1eaeda109..a68cd1c39698e 100644
--- a/llvm/test/CodeGen/Generic/f128-math-lowering.ll
+++ b/llvm/test/CodeGen/Generic/f128-math-lowering.ll
@@ -1,12 +1,15 @@
 ; RUN: llc < %s -mtriple=aarch64-unknown-none -verify-machineinstrs | 
FileCheck %s --check-prefix=CHECK-USELD
-; RUN: llc < %s -mtriple=i686-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-USELD
-; RUN: llc < %s -mtriple=riscv32 -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=i686-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-NOTLD
+; RUN: llc < %s -mtriple=powerpc-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-NOTLD
+; RUN: llc < %s -mtriple=powerpc64-unknown -verify-machineinstrs | FileCheck 
%s --check-prefix=CHECK-NOTLD
+; RUN: llc < %s -mtriple=riscv32 -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-NOTLD
 ; RUN: llc < %s -mtriple=s390x-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-S390X
-; RUN: llc < %s -mtriple=x86_64-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=x86_64-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-NOTLD
 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs | 
FileCheck %s --check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=x86_64-unknown-linux-musl -verify-machineinstrs | 
FileCheck %s --check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-musl -verify-machineinstrs | 
FileCheck %s --check-prefix=CHECK-NOTLD
 ;
 ; REQUIRES: aarch64-registered-target
+; REQUIRES: powerpc-registered-target
 ; REQUIRES: riscv-registered-target
 ; REQUIRES: systemz-registered-target
 ; REQUIRES: x86-registered-target

>From 81c4af35458af36a115c276aeec7b2a75b43e66d Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgr...@umich.edu>
Date: Thu, 27 Feb 2025 09:38:09 +0000
Subject: [PATCH 3/5] Move changes away from f128 libcalls to an adjust
 function

---
 llvm/include/llvm/IR/RuntimeLibcalls.h |  17 ++++
 llvm/lib/IR/RuntimeLibcalls.cpp        | 105 +++++++++++++------------
 2 files changed, 73 insertions(+), 49 deletions(-)

diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h 
b/llvm/include/llvm/IR/RuntimeLibcalls.h
index b3648f5a31e2a..fd1930cce0b05 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -14,9 +14,11 @@
 #ifndef LLVM_IR_RUNTIME_LIBCALLS_H
 #define LLVM_IR_RUNTIME_LIBCALLS_H
 
+#include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/IR/CallingConv.h"
 #include "llvm/Support/AtomicOrdering.h"
+#include "llvm/Target/TargetMachine.h"
 #include "llvm/TargetParser/Triple.h"
 
 namespace llvm {
@@ -38,10 +40,25 @@ enum Libcall {
 
 /// A simple container for information about the supported runtime calls.
 struct RuntimeLibcallsInfo {
+  /// Default libcalls for the triple. Note that `fixupLibcalls` should also be
+  /// called in order to apply machine-specific and configurable behavior.
   explicit RuntimeLibcallsInfo(const Triple &TT) {
     initLibcalls(TT);
   }
 
+  /// Apply nondefault overrides to libcalls based on machine configuration.
+  ///
+  /// @param[in] TM               Used to account for ABI-secific affects on
+  ///                             libcalls.
+  /// @param[in] LongDoubleFormat If set, override the platform default.
+  // TODO: maybe make the option an enum
+  //     enum Fp128LibcallFormat {
+  //         AsF128; // always lower to f128 versions (probably what Rust will 
do)
+  //         AsLongDouble; // always lower f128 as long double (probably what 
Clang should do)
+  //         AsPlatformDefault; // don't change anything
+  //     }
+  void adjustLibcalls(const TargetMachine &TM, const fltSemantics 
*LongDoubleFormat);
+
   /// Rename the default libcall routine name for the specified libcall.
   void setLibcallName(RTLIB::Libcall Call, const char *Name) {
     LibcallRoutineNames[Call] = Name;
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index 2e3b071c8f4bf..01fdd832a5ba6 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -7,6 +7,7 @@
 
//===----------------------------------------------------------------------===//
 
 #include "llvm/IR/RuntimeLibcalls.h"
+#include "llvm/Target/TargetMachine.h"
 
 using namespace llvm;
 using namespace RTLIB;
@@ -25,55 +26,6 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
   for (int LC = 0; LC < RTLIB::UNKNOWN_LIBCALL; ++LC)
     setLibcallCallingConv((RTLIB::Libcall)LC, CallingConv::C);
 
-  // The long double version of library functions is more common than the
-  // f128-specific version. Use these if that is the long double type on the
-  // platform, or if the frontend specifies.
-  if (TT.isLongDoubleF128(""))  {
-    setLibcallName(RTLIB::ACOS_F128, "acosl");
-    setLibcallName(RTLIB::ASIN_F128, "asinl");
-    setLibcallName(RTLIB::ATAN2_F128,"atan2l");
-    setLibcallName(RTLIB::ATAN_F128,"atanl");
-    setLibcallName(RTLIB::CBRT_F128, "cbrtl");
-    setLibcallName(RTLIB::CEIL_F128, "ceill");
-    setLibcallName(RTLIB::COPYSIGN_F128, "copysignl");
-    setLibcallName(RTLIB::COSH_F128, "coshl");
-    setLibcallName(RTLIB::COS_F128, "cosl");
-    setLibcallName(RTLIB::EXP10_F128, "exp10l");
-    setLibcallName(RTLIB::EXP2_F128, "exp2l");
-    setLibcallName(RTLIB::EXP_F128, "expl");
-    setLibcallName(RTLIB::FLOOR_F128, "floorl");
-    setLibcallName(RTLIB::FMAXIMUMNUM_F128, "fmaximum_numl");
-    setLibcallName(RTLIB::FMAXIMUM_F128, "fmaximuml");
-    setLibcallName(RTLIB::FMAX_F128, "fmaxl");
-    setLibcallName(RTLIB::FMA_F128, "fmal");
-    setLibcallName(RTLIB::FMINIMUMNUM_F128, "fminimum_numl");
-    setLibcallName(RTLIB::FMINIMUM_F128, "fminimuml");
-    setLibcallName(RTLIB::FMIN_F128, "fminl");
-    setLibcallName(RTLIB::FREXP_F128, "frexpl");
-    setLibcallName(RTLIB::LDEXP_F128, "ldexpl");
-    setLibcallName(RTLIB::LLRINT_F128, "llrintl");
-    setLibcallName(RTLIB::LLROUND_F128, "llroundl");
-    setLibcallName(RTLIB::LOG10_F128, "log10l");
-    setLibcallName(RTLIB::LOG2_F128, "log2l");
-    setLibcallName(RTLIB::LOG_F128, "logl");
-    setLibcallName(RTLIB::LRINT_F128, "lrintl");
-    setLibcallName(RTLIB::LROUND_F128, "lroundl");
-    setLibcallName(RTLIB::MODF_F128, "modfl");
-    setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintl");
-    setLibcallName(RTLIB::POW_F128, "powl");
-    setLibcallName(RTLIB::REM_F128, "fmodl");
-    setLibcallName(RTLIB::RINT_F128, "rintl");
-    setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenl");
-    setLibcallName(RTLIB::ROUND_F128, "roundl");
-    setLibcallName(RTLIB::SINCOSPI_F128, "sincospil");
-    setLibcallName(RTLIB::SINH_F128, "sinhl");
-    setLibcallName(RTLIB::SIN_F128, "sinl");
-    setLibcallName(RTLIB::SQRT_F128, "sqrtl");
-    setLibcallName(RTLIB::TANH_F128,"tanhl");
-    setLibcallName(RTLIB::TAN_F128,"tanl");
-    setLibcallName(RTLIB::TRUNC_F128, "truncl");
-  }
-
   // For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf".
   if (TT.isPPC()) {
     setLibcallName(RTLIB::ADD_F128, "__addkf3");
@@ -253,3 +205,58 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
     setLibcallName(RTLIB::MULO_I128, nullptr);
   }
 }
+
+void RuntimeLibcallsInfo::adjustLibcalls(const TargetMachine &TM,
+                                         const fltSemantics *LongDoubleFormat) 
{
+
+  const Triple &TT = TM.getTargetTriple();
+
+  // The long double version of library functions is more common than the
+  // f128-specific version. Use these if that is the long double type on the
+  // platform, or if the frontend specifies.
+  if (TT.isLongDoubleF128()) {
+    setLibcallName(RTLIB::ACOS_F128, "acosl");
+    setLibcallName(RTLIB::ASIN_F128, "asinl");
+    setLibcallName(RTLIB::ATAN2_F128, "atan2l");
+    setLibcallName(RTLIB::ATAN_F128, "atanl");
+    setLibcallName(RTLIB::CBRT_F128, "cbrtl");
+    setLibcallName(RTLIB::CEIL_F128, "ceill");
+    setLibcallName(RTLIB::COPYSIGN_F128, "copysignl");
+    setLibcallName(RTLIB::COSH_F128, "coshl");
+    setLibcallName(RTLIB::COS_F128, "cosl");
+    setLibcallName(RTLIB::EXP10_F128, "exp10l");
+    setLibcallName(RTLIB::EXP2_F128, "exp2l");
+    setLibcallName(RTLIB::EXP_F128, "expl");
+    setLibcallName(RTLIB::FLOOR_F128, "floorl");
+    setLibcallName(RTLIB::FMAXIMUMNUM_F128, "fmaximum_numl");
+    setLibcallName(RTLIB::FMAXIMUM_F128, "fmaximuml");
+    setLibcallName(RTLIB::FMAX_F128, "fmaxl");
+    setLibcallName(RTLIB::FMA_F128, "fmal");
+    setLibcallName(RTLIB::FMINIMUMNUM_F128, "fminimum_numl");
+    setLibcallName(RTLIB::FMINIMUM_F128, "fminimuml");
+    setLibcallName(RTLIB::FMIN_F128, "fminl");
+    setLibcallName(RTLIB::FREXP_F128, "frexpl");
+    setLibcallName(RTLIB::LDEXP_F128, "ldexpl");
+    setLibcallName(RTLIB::LLRINT_F128, "llrintl");
+    setLibcallName(RTLIB::LLROUND_F128, "llroundl");
+    setLibcallName(RTLIB::LOG10_F128, "log10l");
+    setLibcallName(RTLIB::LOG2_F128, "log2l");
+    setLibcallName(RTLIB::LOG_F128, "logl");
+    setLibcallName(RTLIB::LRINT_F128, "lrintl");
+    setLibcallName(RTLIB::LROUND_F128, "lroundl");
+    setLibcallName(RTLIB::MODF_F128, "modfl");
+    setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintl");
+    setLibcallName(RTLIB::POW_F128, "powl");
+    setLibcallName(RTLIB::REM_F128, "fmodl");
+    setLibcallName(RTLIB::RINT_F128, "rintl");
+    setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenl");
+    setLibcallName(RTLIB::ROUND_F128, "roundl");
+    setLibcallName(RTLIB::SINCOSPI_F128, "sincospil");
+    setLibcallName(RTLIB::SINH_F128, "sinhl");
+    setLibcallName(RTLIB::SIN_F128, "sinl");
+    setLibcallName(RTLIB::SQRT_F128, "sqrtl");
+    setLibcallName(RTLIB::TANH_F128, "tanhl");
+    setLibcallName(RTLIB::TAN_F128, "tanl");
+    setLibcallName(RTLIB::TRUNC_F128, "truncl");
+  }
+}

>From 74cfe4d47bb4ad1a7b6c0fb8ee4412ebdbab485a Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgr...@umich.edu>
Date: Sat, 1 Mar 2025 05:53:35 +0000
Subject: [PATCH 4/5] Move to a module flag

---
 clang/test/CodeGen/f128-math-lowering.c       |  15 ++
 llvm/include/llvm/IR/Module.h                 |   7 +
 llvm/include/llvm/IR/RuntimeLibcalls.def      |   3 +-
 llvm/include/llvm/IR/RuntimeLibcalls.h        |  48 ++++--
 llvm/include/llvm/Target/TargetOptions.h      |   6 +-
 llvm/lib/CodeGen/TargetLoweringBase.cpp       |   1 +
 llvm/lib/IR/Module.cpp                        |  18 +-
 llvm/lib/IR/RuntimeLibcalls.cpp               |  99 +++++------
 llvm/lib/LTO/LTO.cpp                          |   1 +
 llvm/lib/Object/IRSymtab.cpp                  |  16 +-
 .../CodeGen/Generic/f128-math-lowering.ll     | 162 ++++++++++--------
 11 files changed, 222 insertions(+), 154 deletions(-)
 create mode 100644 clang/test/CodeGen/f128-math-lowering.c

diff --git a/clang/test/CodeGen/f128-math-lowering.c 
b/clang/test/CodeGen/f128-math-lowering.c
new file mode 100644
index 0000000000000..aa58238faad92
--- /dev/null
+++ b/clang/test/CodeGen/f128-math-lowering.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple x86_64-linux-android -emit-llvm -o - %s \
+// RUN:    | FileCheck %s --check-prefix=A64
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s \
+// RUN:    | FileCheck %s --check-prefix=G64
+// RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm -o - %s \
+// RUN:    | FileCheck %s --check-prefix=P64
+// RUN: %clang_cc1 -triple i686-linux-android -emit-llvm -o - %s \
+// RUN:    | FileCheck %s --check-prefix=A32
+// RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm -o - %s \
+// RUN:    | FileCheck %s --check-prefix=G32
+// RUN: %clang_cc1 -triple powerpc-linux-gnu -emit-llvm -o - %s \
+// RUN:    | FileCheck %s --check-prefix=P32
+// RUN: %clang_cc1 -triple x86_64-nacl -emit-llvm -o - %s \
+// RUN:    | FileCheck %s --check-prefix=N64
+
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index 12b50fc506516..ebb7b82adac19 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -28,6 +28,7 @@
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/ProfileSummary.h"
+#include "llvm/IR/RuntimeLibcalls.h"
 #include "llvm/IR/SymbolTableListTraits.h"
 #include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/CodeGen.h"
@@ -1065,6 +1066,12 @@ class LLVM_ABI Module {
 
   /// Set the target variant version build SDK version metadata.
   void setDarwinTargetVariantSDKVersion(VersionTuple Version);
+
+  /// Rather than using the default `sinf128(_Float128)`-style libcalls for
+  /// `fp128`, lower to sinl(long double)`-style. This may be desirable in
+  /// cases where system `long double` is format- and ABI-compatible with
+  /// `_Float128` but the system libm does not provide `*f128` symbols.
+  void setF128LibcallFormat(F128LibcallFormat LibcallFmt);
 };
 
 /// Given "llvm.used" or "llvm.compiler.used" as a global name, collect the
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.def 
b/llvm/include/llvm/IR/RuntimeLibcalls.def
index 515b484cab343..c7dfef9002020 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.def
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.def
@@ -86,7 +86,8 @@ HANDLE_LIBCALL(CTLZ_I32, "__clzsi2")
 HANDLE_LIBCALL(CTLZ_I64, "__clzdi2")
 HANDLE_LIBCALL(CTLZ_I128, "__clzti2")
 
-// Floating-point
+// Floating-point. Note that new fp128 math routines should also be added to
+// setF128LibcallFormat in RuntimeLibcalls.cpp.
 HANDLE_LIBCALL(ADD_F32, "__addsf3")
 HANDLE_LIBCALL(ADD_F64, "__adddf3")
 HANDLE_LIBCALL(ADD_F80, "__addxf3")
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h 
b/llvm/include/llvm/IR/RuntimeLibcalls.h
index fd1930cce0b05..4ffa5a267815a 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -22,6 +22,17 @@
 #include "llvm/TargetParser/Triple.h"
 
 namespace llvm {
+
+/// Library names to use for `fp128` libcalls.
+// If needed, this could be extended with a `Quadmath` option for `q`-suffixed
+// `libquadmath` symbols.
+enum class F128LibcallFormat {
+  /// C23 `*f128` lowering, e.g. `sinf128`
+  Default = 0,
+  /// `long double` *l` lowering, e.g. `sinl`.
+  LongDouble = 1,
+};
+
 namespace RTLIB {
 
 /// RTLIB::Libcall enum - This enum defines all of the runtime library calls
@@ -42,22 +53,7 @@ enum Libcall {
 struct RuntimeLibcallsInfo {
   /// Default libcalls for the triple. Note that `fixupLibcalls` should also be
   /// called in order to apply machine-specific and configurable behavior.
-  explicit RuntimeLibcallsInfo(const Triple &TT) {
-    initLibcalls(TT);
-  }
-
-  /// Apply nondefault overrides to libcalls based on machine configuration.
-  ///
-  /// @param[in] TM               Used to account for ABI-secific affects on
-  ///                             libcalls.
-  /// @param[in] LongDoubleFormat If set, override the platform default.
-  // TODO: maybe make the option an enum
-  //     enum Fp128LibcallFormat {
-  //         AsF128; // always lower to f128 versions (probably what Rust will 
do)
-  //         AsLongDouble; // always lower f128 as long double (probably what 
Clang should do)
-  //         AsPlatformDefault; // don't change anything
-  //     }
-  void adjustLibcalls(const TargetMachine &TM, const fltSemantics 
*LongDoubleFormat);
+  explicit RuntimeLibcallsInfo(const Triple &TT) { initLibcalls(TT); }
 
   /// Rename the default libcall routine name for the specified libcall.
   void setLibcallName(RTLIB::Libcall Call, const char *Name) {
@@ -89,6 +85,26 @@ struct RuntimeLibcallsInfo {
                             LibcallRoutineNames + RTLIB::UNKNOWN_LIBCALL);
   }
 
+  /// Set a specific lowering convention for `fp128` math libcalls.
+  ///
+  /// By default, `fp128` math functions get lowered to the C23 `sinf128`-
+  /// style symbols. This allows overriding with `sinl`-style symbols on
+  /// platforms where `long double` is known to be identical to _Float128.
+  /// versions, e.g. `sinf128`.
+  void setF128LibcallFormat(F128LibcallFormat Format);
+
+  /// Set the `fp128` libcall format from a module flag.
+  void setF128LibcallFormatFromInt(uint32_t Val) {
+    fprintf(stderr, "setting flag\n");
+    if (Val == static_cast<uint32_t>(F128LibcallFormat::LongDouble)) {
+      setF128LibcallFormat(F128LibcallFormat::LongDouble);
+    } else {
+      setF128LibcallFormat(F128LibcallFormat::Default);
+    }
+  }
+
+  static constexpr const StringRef F128LibcallModuleId = "Fp128 Libcall 
Format";
+
 private:
   /// Stores the name each libcall.
   const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1];
diff --git a/llvm/include/llvm/Target/TargetOptions.h 
b/llvm/include/llvm/Target/TargetOptions.h
index fd8dad4f6f791..6ec03431ab529 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -15,6 +15,7 @@
 #define LLVM_TARGET_TARGETOPTIONS_H
 
 #include "llvm/ADT/FloatingPointMode.h"
+#include "llvm/IR/RuntimeLibcalls.h"
 #include "llvm/MC/MCTargetOptions.h"
 
 #include <memory>
@@ -154,7 +155,8 @@ namespace llvm {
           PPCGenScalarMASSEntries(false), JMCInstrument(false),
           EnableCFIFixup(false), MisExpect(false), 
XCOFFReadOnlyPointers(false),
           VerifyArgABICompliance(true),
-          FPDenormalMode(DenormalMode::IEEE, DenormalMode::IEEE) {}
+          FPDenormalMode(DenormalMode::IEEE, DenormalMode::IEEE),
+          F128LibcallFormat(F128LibcallFormat::Default) {}
 
     /// DisableFramePointerElim - This returns true if frame pointer 
elimination
     /// optimization should be disabled for the given machine function.
@@ -433,6 +435,8 @@ namespace llvm {
     /// Which debugger to tune for.
     DebuggerKind DebuggerTuning = DebuggerKind::Default;
 
+    llvm::F128LibcallFormat F128LibcallFormat;
+
   private:
     /// Flushing mode to assume in default FP environment.
     DenormalMode FPDenormalMode;
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp 
b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index f5ea3c0b47d6a..4dc5dbc1151a4 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -662,6 +662,7 @@ TargetLoweringBase::TargetLoweringBase(const TargetMachine 
&tm)
   SupportsUnalignedAtomics = false;
 
   RTLIB::initCmpLibcallCCs(CmpLibcallCCs);
+  Libcalls.setF128LibcallFormat(tm.Options.F128LibcallFormat);
 }
 
 void TargetLoweringBase::initActions() {
diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp
index c7b9f8744d8d3..ba51a3d74b67b 100644
--- a/llvm/lib/IR/Module.cpp
+++ b/llvm/lib/IR/Module.cpp
@@ -32,6 +32,7 @@
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/IR/RuntimeLibcalls.h"
 #include "llvm/IR/SymbolTableListTraits.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/TypeFinder.h"
@@ -209,7 +210,7 @@ FunctionCallee Module::getOrInsertFunction(StringRef Name, 
FunctionType *Ty,
     // Nope, add it
     Function *New = Function::Create(Ty, GlobalVariable::ExternalLinkage,
                                      DL.getProgramAddressSpace(), Name, this);
-    if (!New->isIntrinsic())       // Intrinsics get attrs set on construction
+    if (!New->isIntrinsic()) // Intrinsics get attrs set on construction
       New->setAttributes(AttributeList);
     return {Ty, New}; // Return the new prototype.
   }
@@ -243,7 +244,7 @@ Function *Module::getFunction(StringRef Name) const {
 GlobalVariable *Module::getGlobalVariable(StringRef Name,
                                           bool AllowLocal) const {
   if (GlobalVariable *Result =
-      dyn_cast_or_null<GlobalVariable>(getNamedValue(Name)))
+          dyn_cast_or_null<GlobalVariable>(getNamedValue(Name)))
     if (AllowLocal || !Result->hasLocalLinkage())
       return Result;
   return nullptr;
@@ -334,10 +335,11 @@ bool Module::isValidModFlagBehavior(Metadata *MD, 
ModFlagBehavior &MFB) {
 }
 
 /// getModuleFlagsMetadata - Returns the module flags in the provided vector.
-void Module::
-getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const {
+void Module::getModuleFlagsMetadata(
+    SmallVectorImpl<ModuleFlagEntry> &Flags) const {
   const NamedMDNode *ModFlags = getModuleFlagsMetadata();
-  if (!ModFlags) return;
+  if (!ModFlags)
+    return;
 
   for (const MDNode *Flag : ModFlags->operands()) {
     // The verifier will catch errors, so no need to check them here.
@@ -915,3 +917,9 @@ VersionTuple Module::getDarwinTargetVariantSDKVersion() 
const {
 void Module::setDarwinTargetVariantSDKVersion(VersionTuple Version) {
   addSDKVersionMD(Version, *this, "darwin.target_variant.SDK Version");
 }
+
+void Module::setF128LibcallFormat(F128LibcallFormat Format) {
+  addModuleFlag(ModFlagBehavior::Error,
+                RTLIB::RuntimeLibcallsInfo::F128LibcallModuleId,
+                static_cast<uint32_t>(Format));
+}
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index 01fdd832a5ba6..de0cfe7b35796 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -206,57 +206,50 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
   }
 }
 
-void RuntimeLibcallsInfo::adjustLibcalls(const TargetMachine &TM,
-                                         const fltSemantics *LongDoubleFormat) 
{
-
-  const Triple &TT = TM.getTargetTriple();
-
-  // The long double version of library functions is more common than the
-  // f128-specific version. Use these if that is the long double type on the
-  // platform, or if the frontend specifies.
-  if (TT.isLongDoubleF128()) {
-    setLibcallName(RTLIB::ACOS_F128, "acosl");
-    setLibcallName(RTLIB::ASIN_F128, "asinl");
-    setLibcallName(RTLIB::ATAN2_F128, "atan2l");
-    setLibcallName(RTLIB::ATAN_F128, "atanl");
-    setLibcallName(RTLIB::CBRT_F128, "cbrtl");
-    setLibcallName(RTLIB::CEIL_F128, "ceill");
-    setLibcallName(RTLIB::COPYSIGN_F128, "copysignl");
-    setLibcallName(RTLIB::COSH_F128, "coshl");
-    setLibcallName(RTLIB::COS_F128, "cosl");
-    setLibcallName(RTLIB::EXP10_F128, "exp10l");
-    setLibcallName(RTLIB::EXP2_F128, "exp2l");
-    setLibcallName(RTLIB::EXP_F128, "expl");
-    setLibcallName(RTLIB::FLOOR_F128, "floorl");
-    setLibcallName(RTLIB::FMAXIMUMNUM_F128, "fmaximum_numl");
-    setLibcallName(RTLIB::FMAXIMUM_F128, "fmaximuml");
-    setLibcallName(RTLIB::FMAX_F128, "fmaxl");
-    setLibcallName(RTLIB::FMA_F128, "fmal");
-    setLibcallName(RTLIB::FMINIMUMNUM_F128, "fminimum_numl");
-    setLibcallName(RTLIB::FMINIMUM_F128, "fminimuml");
-    setLibcallName(RTLIB::FMIN_F128, "fminl");
-    setLibcallName(RTLIB::FREXP_F128, "frexpl");
-    setLibcallName(RTLIB::LDEXP_F128, "ldexpl");
-    setLibcallName(RTLIB::LLRINT_F128, "llrintl");
-    setLibcallName(RTLIB::LLROUND_F128, "llroundl");
-    setLibcallName(RTLIB::LOG10_F128, "log10l");
-    setLibcallName(RTLIB::LOG2_F128, "log2l");
-    setLibcallName(RTLIB::LOG_F128, "logl");
-    setLibcallName(RTLIB::LRINT_F128, "lrintl");
-    setLibcallName(RTLIB::LROUND_F128, "lroundl");
-    setLibcallName(RTLIB::MODF_F128, "modfl");
-    setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintl");
-    setLibcallName(RTLIB::POW_F128, "powl");
-    setLibcallName(RTLIB::REM_F128, "fmodl");
-    setLibcallName(RTLIB::RINT_F128, "rintl");
-    setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenl");
-    setLibcallName(RTLIB::ROUND_F128, "roundl");
-    setLibcallName(RTLIB::SINCOSPI_F128, "sincospil");
-    setLibcallName(RTLIB::SINH_F128, "sinhl");
-    setLibcallName(RTLIB::SIN_F128, "sinl");
-    setLibcallName(RTLIB::SQRT_F128, "sqrtl");
-    setLibcallName(RTLIB::TANH_F128, "tanhl");
-    setLibcallName(RTLIB::TAN_F128, "tanl");
-    setLibcallName(RTLIB::TRUNC_F128, "truncl");
-  }
+void RuntimeLibcallsInfo::setF128LibcallFormat(F128LibcallFormat Format) {
+  bool UseLD = Format == F128LibcallFormat::LongDouble;
+
+  setLibcallName(RTLIB::ACOS_F128, UseLD ? "acosl" : "acosf128");
+  setLibcallName(RTLIB::ASIN_F128, UseLD ? "asinl" : "asinf128");
+  setLibcallName(RTLIB::ATAN2_F128, UseLD ? "atan2l" : "atan2f128");
+  setLibcallName(RTLIB::ATAN_F128, UseLD ? "atanl" : "atanf128");
+  setLibcallName(RTLIB::CBRT_F128, UseLD ? "cbrtl" : "cbrtf128");
+  setLibcallName(RTLIB::CEIL_F128, UseLD ? "ceill" : "ceilf128");
+  setLibcallName(RTLIB::COPYSIGN_F128, UseLD ? "copysignl" : "copysignf128");
+  setLibcallName(RTLIB::COSH_F128, UseLD ? "coshl" : "coshf128");
+  setLibcallName(RTLIB::COS_F128, UseLD ? "cosl" : "cosf128");
+  setLibcallName(RTLIB::EXP10_F128, UseLD ? "exp10l" : "exp10f128");
+  setLibcallName(RTLIB::EXP2_F128, UseLD ? "exp2l" : "exp2f128");
+  setLibcallName(RTLIB::EXP_F128, UseLD ? "expl" : "expf128");
+  setLibcallName(RTLIB::FLOOR_F128, UseLD ? "floorl" : "floorf128");
+  setLibcallName(RTLIB::FMAXIMUMNUM_F128, UseLD ? "fmaximum_numl" : 
"fmaximum_numf128");
+  setLibcallName(RTLIB::FMAXIMUM_F128, UseLD ? "fmaximuml" : "fmaximumf128");
+  setLibcallName(RTLIB::FMAX_F128, UseLD ? "fmaxl" : "fmaxf128");
+  setLibcallName(RTLIB::FMA_F128, UseLD ? "fmal" : "fmaf128");
+  setLibcallName(RTLIB::FMINIMUMNUM_F128, UseLD ? "fminimum_numl" : 
"fminimum_numf128");
+  setLibcallName(RTLIB::FMINIMUM_F128, UseLD ? "fminimuml" : "fminimumf128");
+  setLibcallName(RTLIB::FMIN_F128, UseLD ? "fminl" : "fminf128");
+  setLibcallName(RTLIB::FREXP_F128, UseLD ? "frexpl" : "frexpf128");
+  setLibcallName(RTLIB::LDEXP_F128, UseLD ? "ldexpl" : "ldexpf128");
+  setLibcallName(RTLIB::LLRINT_F128, UseLD ? "llrintl" : "llrintf128");
+  setLibcallName(RTLIB::LLROUND_F128, UseLD ? "llroundl" : "llroundf128");
+  setLibcallName(RTLIB::LOG10_F128, UseLD ? "log10l" : "log10f128");
+  setLibcallName(RTLIB::LOG2_F128, UseLD ? "log2l" : "log2f128");
+  setLibcallName(RTLIB::LOG_F128, UseLD ? "logl" : "logf128");
+  setLibcallName(RTLIB::LRINT_F128, UseLD ? "lrintl" : "lrintf128");
+  setLibcallName(RTLIB::LROUND_F128, UseLD ? "lroundl" : "lroundf128");
+  setLibcallName(RTLIB::MODF_F128, UseLD ? "modfl" : "modff128");
+  setLibcallName(RTLIB::NEARBYINT_F128, UseLD ? "nearbyintl" : 
"nearbyintf128");
+  setLibcallName(RTLIB::POW_F128, UseLD ? "powl" : "powf128");
+  setLibcallName(RTLIB::REM_F128, UseLD ? "fmodl" : "fmodf128");
+  setLibcallName(RTLIB::RINT_F128, UseLD ? "rintl" : "rintf128");
+  setLibcallName(RTLIB::ROUNDEVEN_F128, UseLD ? "roundevenl" : 
"roundevenf128");
+  setLibcallName(RTLIB::ROUND_F128, UseLD ? "roundl" : "roundf128");
+  setLibcallName(RTLIB::SINCOSPI_F128, UseLD ? "sincospil" : "sincospif128");
+  setLibcallName(RTLIB::SINH_F128, UseLD ? "sinhl" : "sinhf128");
+  setLibcallName(RTLIB::SIN_F128, UseLD ? "sinl" : "sinf128");
+  setLibcallName(RTLIB::SQRT_F128, UseLD ? "sqrtl" : "sqrtf128");
+  setLibcallName(RTLIB::TANH_F128, UseLD ? "tanhl" : "tanhf128");
+  setLibcallName(RTLIB::TAN_F128, UseLD ? "tanl" : "tanf128");
+  setLibcallName(RTLIB::TRUNC_F128, UseLD ? "truncl" : "truncf128");
 }
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 0f53c60851217..213dd5c47832a 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -1380,6 +1380,7 @@ Error LTO::runRegularLTO(AddStreamFn AddStream) {
 }
 
 SmallVector<const char *> LTO::getRuntimeLibcallSymbols(const Triple &TT) {
+  fprintf(stderr, "call from lto\n");
   RTLIB::RuntimeLibcallsInfo Libcalls(TT);
   SmallVector<const char *> LibcallSymbols;
   copy_if(Libcalls.getLibcallNames(), std::back_inserter(LibcallSymbols),
diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp
index 2a2b235461a55..96b5726d7c305 100644
--- a/llvm/lib/Object/IRSymtab.cpp
+++ b/llvm/lib/Object/IRSymtab.cpp
@@ -16,6 +16,7 @@
 #include "llvm/Bitcode/BitcodeReader.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/IR/Comdat.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/GlobalAlias.h"
 #include "llvm/IR/GlobalObject.h"
@@ -213,11 +214,21 @@ Expected<int> Builder::getComdatIndex(const Comdat *C, 
const Module *M) {
   return P.first->second;
 }
 
-static DenseSet<StringRef> buildPreservedSymbolsSet(const Triple &TT) {
+/// Initialize a set with the platform's libcalls.
+static DenseSet<StringRef> buildPreservedSymbolsSet(const Module *M) {
   DenseSet<StringRef> PreservedSymbolSet(std::begin(PreservedSymbols),
                                          std::end(PreservedSymbols));
 
+  const Triple &TT = llvm::Triple(M->getTargetTriple());
   RTLIB::RuntimeLibcallsInfo Libcalls(TT);
+
+  // Configure libcalls based on module flags.
+  const auto *Flag = mdconst::extract_or_null<ConstantInt>(
+      M->getModuleFlag(RTLIB::RuntimeLibcallsInfo::F128LibcallModuleId));
+  Libcalls.setF128LibcallFormatFromInt(Flag->getZExtValue());
+
+  fprintf(stderr, "AOJDSFOIDOIFJD %d\n", Flag->getZExtValue());
+
   for (const char *Name : Libcalls.getLibcallNames()) {
     if (Name)
       PreservedSymbolSet.insert(Name);
@@ -281,8 +292,7 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
   setStr(Sym.IRName, GV->getName());
 
   static const DenseSet<StringRef> PreservedSymbolsSet =
-      buildPreservedSymbolsSet(
-          llvm::Triple(GV->getParent()->getTargetTriple()));
+      buildPreservedSymbolsSet(GV->getParent());
   bool IsPreservedSymbol = PreservedSymbolsSet.contains(GV->getName());
 
   if (Used.count(GV) || IsPreservedSymbol)
diff --git a/llvm/test/CodeGen/Generic/f128-math-lowering.ll 
b/llvm/test/CodeGen/Generic/f128-math-lowering.ll
index a68cd1c39698e..d8ed0f9d84663 100644
--- a/llvm/test/CodeGen/Generic/f128-math-lowering.ll
+++ b/llvm/test/CodeGen/Generic/f128-math-lowering.ll
@@ -1,12 +1,22 @@
-; RUN: llc < %s -mtriple=aarch64-unknown-none -verify-machineinstrs | 
FileCheck %s --check-prefix=CHECK-USELD
-; RUN: llc < %s -mtriple=i686-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=powerpc-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=powerpc64-unknown -verify-machineinstrs | FileCheck 
%s --check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=riscv32 -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=s390x-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-S390X
-; RUN: llc < %s -mtriple=x86_64-unknown -verify-machineinstrs | FileCheck %s 
--check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs | 
FileCheck %s --check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=x86_64-unknown-linux-musl -verify-machineinstrs | 
FileCheck %s --check-prefix=CHECK-NOTLD
+; 
+; RUN: llc < %s -mtriple=aarch64-unknown-none -verify-machineinstrs | 
FileCheck %s --check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=i686-unknown -verify-machineinstrs | FileCheck %s 
--check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=powerpc-unknown -verify-machineinstrs | FileCheck %s 
--check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=powerpc64-unknown -verify-machineinstrs | FileCheck 
%s --check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=riscv32 -verify-machineinstrs | FileCheck %s 
--check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=s390x-unknown -verify-machineinstrs | FileCheck %s 
--check-prefixes=CHECK,CHECK-S390X
+; RUN: llc < %s -mtriple=x86_64-unknown -verify-machineinstrs | FileCheck %s 
--check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs | 
FileCheck %s --check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-musl -verify-machineinstrs | 
FileCheck %s --check-prefixes=CHECK,CHECK-F128
+; RUN: sed 's/; flag://' %s | llc -mtriple=aarch64-unknown-none 
-verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=i686-unknown -verify-machineinstrs 
| FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=powerpc-unknown 
-verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=powerpc64-unknown 
-verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=riscv32 -verify-machineinstrs | 
FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=s390x-unknown -verify-machineinstrs 
| FileCheck %s --check-prefixes=CHECK,CHECK-S390X
+; RUN: sed 's/; flag://' %s | llc -mtriple=x86_64-unknown 
-verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=x86_64-unknown-linux-gnu 
-verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=x86_64-unknown-linux-musl 
-verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
 ;
 ; REQUIRES: aarch64-registered-target
 ; REQUIRES: powerpc-registered-target
@@ -24,16 +34,16 @@
 ; * riscv32 (long double == f64)
 ; * s390x (long double == f128, hardware support)
 ; * A couple assorted environments for x86
-;
-; FIXME: only targets where long double is `f128` should be using `USELD`, all
-; others need to be NOTLD. PowerPC should be added but it currently emits an
-; interesting blend of both (e.g. `acosl` but `ceilf128`).
+
+
+; flag: !0 = !{ i32 1, !"Fp128 Libcall Format", i32 1 }
+; flag: !llvm.module.flags = !{ !0 }
 
 define fp128 @test_acosf128(fp128 %a) {
 ; CHECK-LABEL:      test_acosf128:
-; CHECK-NOTLD:      acosf128
+; CHECK-F128:       acosf128
 ; CHECK-USELD:      acosl
-; CHECK-S390X:      acosl
+; CHECK-S390X:      acosf128
 start:
   %0 = tail call fp128 @llvm.acos.f128(fp128 %a)
   ret fp128 %0
@@ -41,9 +51,9 @@ start:
 
 define fp128 @test_asinf128(fp128 %a) {
 ; CHECK-LABEL:      test_asinf128:
-; CHECK-NOTLD:      asinf128
+; CHECK-F128:       asinf128
 ; CHECK-USELD:      asinl
-; CHECK-S390X:      asinl
+; CHECK-S390X:      asinf128
 start:
   %0 = tail call fp128 @llvm.asin.f128(fp128 %a)
   ret fp128 %0
@@ -51,9 +61,9 @@ start:
 
 define fp128 @test_atanf128(fp128 %a) {
 ; CHECK-LABEL:      test_atanf128:
-; CHECK-NOTLD:      atanf128
+; CHECK-F128:       atanf128
 ; CHECK-USELD:      atanl
-; CHECK-S390X:      atanl
+; CHECK-S390X:      atanf128
 start:
   %0 = tail call fp128 @llvm.atan.f128(fp128 %a)
   ret fp128 %0
@@ -61,19 +71,20 @@ start:
 
 define fp128 @test_ceilf128(fp128 %a) {
 ; CHECK-LABEL:      test_ceilf128:
-; CHECK-NOTLD:      ceilf128
+; CHECK-F128:       ceilf128
 ; CHECK-USELD:      ceill
-; CHECK-S390X:      ceill
+; CHECK-S390X:      ceilf128
 start:
   %0 = tail call fp128 @llvm.ceil.f128(fp128 %a)
   ret fp128 %0
 }
 
 define fp128 @test_copysignf128(fp128 %a, fp128 %b) {
-; copysign should always get lowered to assembly
+; copysign should always get lowered to assembly. Regex is needed so as not to
+; match the label.
 ; CHECK-LABEL:      test_copysignf128:
-; CHECK-NOT:        copysignl
-; CHECK-NOT:        copysignf128
+; CHECK-NOT:        {{(^|[[:space:]])fabsf128($|[[:space:]])}}
+; CHECK-NOT:        {{(^|[[:space:]])fabsl($|[[:space:]])}}
 start:
   %0 = tail call fp128 @llvm.copysign.f128(fp128 %a, fp128 %b)
   ret fp128 %0
@@ -81,19 +92,19 @@ start:
 
 define fp128 @test_cosf128(fp128 %a) {
 ; CHECK-LABEL:      test_cosf128:
-; CHECK-NOTLD:      cosf128
+; CHECK-F128:       cosf128
 ; CHECK-USELD:      cosl
-; CHECK-S390X:      cosl
+; CHECK-S390X:      cosf128
 start:
   %0 = tail call fp128 @llvm.cos.f128(fp128 %a)
   ret fp128 %0
 }
 
 define fp128 @test_exp10f128(fp128 %a) {
-; CHECK-LABEL:      test_exp2f128:
-; CHECK-NOTLD:      exp10f128
+; CHECK-LABEL:      test_exp10f128:
+; CHECK-F128:       exp10f128
 ; CHECK-USELD:      exp10l
-; CHECK-S390X:      exp10l
+; CHECK-S390X:      exp10f128
 start:
   %0 = tail call fp128 @llvm.exp10.f128(fp128 %a)
   ret fp128 %0
@@ -101,9 +112,9 @@ start:
 
 define fp128 @test_exp2f128(fp128 %a) {
 ; CHECK-LABEL:      test_exp2f128:
-; CHECK-NOTLD:      exp2f128
+; CHECK-F128:       exp2f128
 ; CHECK-USELD:      exp2l
-; CHECK-S390X:      exp2l
+; CHECK-S390X:      exp2f128
 start:
   %0 = tail call fp128 @llvm.exp2.f128(fp128 %a)
   ret fp128 %0
@@ -112,19 +123,20 @@ start:
 
 define fp128 @test_expf128(fp128 %a) {
 ; CHECK-LABEL:      test_expf128:
-; CHECK-NOTLD:      expf128
+; CHECK-F128:       expf128
 ; CHECK-USELD:      expl
-; CHECK-S390X:      expl
+; CHECK-S390X:      expf128
 start:
   %0 = tail call fp128 @llvm.exp.f128(fp128 %a)
   ret fp128 %0
 }
 
 define fp128 @test_fabsf128(fp128 %a) {
-; fabs should always get lowered to assembly
+; fabs should always get lowered to assembly. Regex is needed so as not to
+; match the label.
 ; CHECK-LABEL:      test_fabsf128:
-; CHECK-NOT:        fabsl
-; CHECK-NOT:        fabsf128
+; CHECK-NOT:        {{(^|[[:space:]])fabsf128($|[[:space:]])}}
+; CHECK-NOT:        {{(^|[[:space:]])fabsl($|[[:space:]])}}
 start:
   %0 = tail call fp128 @llvm.fabs.f128(fp128 %a)
   ret fp128 %0
@@ -132,9 +144,9 @@ start:
 
 define fp128 @test_floorf128(fp128 %a) {
 ; CHECK-LABEL:      test_floorf128:
-; CHECK-NOTLD:      floorf128
+; CHECK-F128:       floorf128
 ; CHECK-USELD:      floorl
-; CHECK-S390X:      floorl
+; CHECK-S390X:      floorf128
 start:
   %0 = tail call fp128 @llvm.floor.f128(fp128 %a)
   ret fp128 %0
@@ -142,9 +154,9 @@ start:
 
 define fp128 @test_fmaf128(fp128 %a, fp128 %b, fp128 %c) {
 ; CHECK-LABEL:      test_fmaf128:
-; CHECK-NOTLD:      fmaf128
+; CHECK-F128:       fmaf128
 ; CHECK-USELD:      fmal
-; CHECK-S390X:      fmal
+; CHECK-S390X:      fmaf128
 start:
   %0 = tail call fp128 @llvm.fma.f128(fp128 %a, fp128 %b, fp128 %c)
   ret fp128 %0
@@ -152,9 +164,9 @@ start:
 
 define { fp128, i32 } @test_frexpf128(fp128 %a) {
 ; CHECK-LABEL:      test_frexpf128:
-; CHECK-NOTLD:      frexpf128
+; CHECK-F128:       frexpf128
 ; CHECK-USELD:      frexpl
-; CHECK-S390X:      frexpl
+; CHECK-S390X:      frexpf128
 start:
   %0 = tail call { fp128, i32 } @llvm.frexp.f128(fp128 %a)
   ret { fp128, i32 } %0
@@ -162,9 +174,9 @@ start:
 
 define fp128 @test_ldexpf128(fp128 %a, i32 %b) {
 ; CHECK-LABEL:      test_ldexpf128:
-; CHECK-NOTLD:      ldexpf128
+; CHECK-F128:       ldexpf128
 ; CHECK-USELD:      ldexpl
-; CHECK-S390X:      ldexpl
+; CHECK-S390X:      ldexpf128
 start:
   %0 = tail call fp128 @llvm.ldexp.f128(fp128 %a, i32 %b)
   ret fp128 %0
@@ -172,9 +184,9 @@ start:
 
 define i64 @test_llrintf128(fp128 %a) {
 ; CHECK-LABEL:      test_llrintf128:
-; CHECK-NOTLD:      llrintf128
+; CHECK-F128:       llrintf128
 ; CHECK-USELD:      llrintl
-; CHECK-S390X:      llrintl
+; CHECK-S390X:      llrintf128
 start:
   %0 = tail call i64 @llvm.llrint.f128(fp128 %a)
   ret i64 %0
@@ -182,9 +194,9 @@ start:
 
 define i64 @test_llroundf128(fp128 %a) {
 ; CHECK-LABEL:      test_llroundf128:
-; CHECK-NOTLD:      llroundf128
+; CHECK-F128:       llroundf128
 ; CHECK-USELD:      llroundl
-; CHECK-S390X:      llroundl
+; CHECK-S390X:      llroundf128
 start:
   %0 = tail call i64 @llvm.llround.i64.f128(fp128 %a)
   ret i64 %0
@@ -192,9 +204,9 @@ start:
 
 define fp128 @test_log10f128(fp128 %a) {
 ; CHECK-LABEL:      test_log10f128:
-; CHECK-NOTLD:      log10f128
+; CHECK-F128:       log10f128
 ; CHECK-USELD:      log10l
-; CHECK-S390X:      log10l
+; CHECK-S390X:      log10f128
 start:
   %0 = tail call fp128 @llvm.log10.f128(fp128 %a)
   ret fp128 %0
@@ -202,9 +214,9 @@ start:
 
 define fp128 @test_log2f128(fp128 %a) {
 ; CHECK-LABEL:      test_log2f128:
-; CHECK-NOTLD:      log2f128
+; CHECK-F128:       log2f128
 ; CHECK-USELD:      log2l
-; CHECK-S390X:      log2l
+; CHECK-S390X:      log2f128
 start:
   %0 = tail call fp128 @llvm.log2.f128(fp128 %a)
   ret fp128 %0
@@ -212,19 +224,19 @@ start:
 
 define fp128 @test_logf128(fp128 %a) {
 ; CHECK-LABEL:      test_logf128:
-; CHECK-NOTLD:      logf128
+; CHECK-F128:       logf128
 ; CHECK-USELD:      logl
-; CHECK-S390X:      logl
+; CHECK-S390X:      logf128
 start:
   %0 = tail call fp128 @llvm.log.f128(fp128 %a)
   ret fp128 %0
 }
 
 define i64 @test_lrintf128(fp128 %a) {
-; CHECK-LABEL:      test_exp2f128:
-; CHECK-NOTLD:      lrintf128
+; CHECK-LABEL:      test_lrintf128:
+; CHECK-F128:       lrintf128
 ; CHECK-USELD:      lrintl
-; CHECK-S390X:      lrintl
+; CHECK-S390X:      lrintf128
 start:
   %0 = tail call i64 @llvm.lrint.f128(fp128 %a)
   ret i64 %0
@@ -232,9 +244,9 @@ start:
 
 define i64 @test_lroundf128(fp128 %a) {
 ; CHECK-LABEL:      test_lroundf128:
-; CHECK-NOTLD:      lroundf128
+; CHECK-F128:       lroundf128
 ; CHECK-USELD:      lroundl
-; CHECK-S390X:      lroundl
+; CHECK-S390X:      lroundf128
 start:
   %0 = tail call i64 @llvm.lround.i64.f128(fp128 %a)
   ret i64 %0
@@ -242,9 +254,9 @@ start:
 
 define fp128 @test_nearbyintf128(fp128 %a) {
 ; CHECK-LABEL:      test_nearbyintf128:
-; CHECK-NOTLD:      nearbyintf128
+; CHECK-F128:       nearbyintf128
 ; CHECK-USELD:      nearbyintl
-; CHECK-S390X:      nearbyintl
+; CHECK-S390X:      nearbyintf128
 start:
   %0 = tail call fp128 @llvm.nearbyint.f128(fp128 %a)
   ret fp128 %0
@@ -252,9 +264,9 @@ start:
 
 define fp128 @test_powf128(fp128 %a, fp128 %b) {
 ; CHECK-LABEL:      test_powf128:
-; CHECK-NOTLD:      powf128
+; CHECK-F128:       powf128
 ; CHECK-USELD:      powl
-; CHECK-S390X:      powl
+; CHECK-S390X:      powf128
 start:
   %0 = tail call fp128 @llvm.pow.f128(fp128 %a, fp128 %b)
   ret fp128 %0
@@ -262,7 +274,7 @@ start:
 
 define fp128 @test_rintf128(fp128 %a) {
 ; CHECK-LABEL:      test_rintf128:
-; CHECK-NOTLD:      rintf128
+; CHECK-F128:       rintf128
 ; CHECK-USELD:      rintl
 ; CHECK-S390X:      fixbr {{%.*}}, 0, {{%.*}}
 start:
@@ -272,9 +284,9 @@ start:
 
 define fp128 @test_roundevenf128(fp128 %a) {
 ; CHECK-LABEL:      test_roundevenf128:
-; CHECK-NOTLD:      roundevenf128
+; CHECK-F128:       roundevenf128
 ; CHECK-USELD:      roundevenl
-; CHECK-S390X:      roundevenl
+; CHECK-S390X:      roundevenf128
 start:
   %0 = tail call fp128 @llvm.roundeven.f128(fp128 %a)
   ret fp128 %0
@@ -282,9 +294,9 @@ start:
 
 define fp128 @test_roundf128(fp128 %a) {
 ; CHECK-LABEL:      test_roundf128:
-; CHECK-NOTLD:      roundf128
+; CHECK-F128:       roundf128
 ; CHECK-USELD:      roundl
-; CHECK-S390X:      roundl
+; CHECK-S390X:      roundf128
 start:
   %0 = tail call fp128 @llvm.round.f128(fp128 %a)
   ret fp128 %0
@@ -292,9 +304,9 @@ start:
 
 define fp128 @test_sinf128(fp128 %a) {
 ; CHECK-LABEL:      test_sinf128:
-; CHECK-NOTLD:      sinf128
+; CHECK-F128:       sinf128
 ; CHECK-USELD:      sinl
-; CHECK-S390X:      sinl
+; CHECK-S390X:      sinf128
 start:
   %0 = tail call fp128 @llvm.sin.f128(fp128 %a)
   ret fp128 %0
@@ -302,7 +314,7 @@ start:
 
 define fp128 @test_sqrtf128(fp128 %a) {
 ; CHECK-LABEL:      test_sqrtf128:
-; CHECK-NOTLD:      sqrtf128
+; CHECK-F128:       sqrtf128
 ; CHECK-USELD:      sqrtl
 ; CHECK-S390X:      sqxbr {{%.*}}, {{%.*}}
 start:
@@ -312,9 +324,9 @@ start:
 
 define fp128 @test_tanf128(fp128 %a) {
 ; CHECK-LABEL:      test_tanf128:
-; CHECK-NOTLD:      tanf128
+; CHECK-F128:       tanf128
 ; CHECK-USELD:      tanl
-; CHECK-S390X:      tanl
+; CHECK-S390X:      tanf128
 start:
   %0 = tail call fp128 @llvm.tan.f128(fp128 %a)
   ret fp128 %0
@@ -322,9 +334,9 @@ start:
 
 define fp128 @test_truncf128(fp128 %a) {
 ; CHECK-LABEL:      test_truncf128:
-; CHECK-NOTLD:      truncf128
+; CHECK-F128:       truncf128
 ; CHECK-USELD:      truncl
-; CHECK-S390X:      truncl
+; CHECK-S390X:      truncf128
 start:
   %0 = tail call fp128 @llvm.trunc.f128(fp128 %a)
   ret fp128 %0

>From 70d8c735d66957a9e5cba2cae974639673364c9f Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgr...@umich.edu>
Date: Sun, 27 Apr 2025 04:31:18 +0000
Subject: [PATCH 5/5] Add new musl variants for f128 availability

---
 clang/lib/Basic/Targets.cpp                   |  3 +-
 clang/lib/Driver/Driver.cpp                   |  6 ++--
 .../lib/Driver/ToolChains/Arch/LoongArch.cpp  |  2 ++
 clang/lib/Driver/ToolChains/Linux.cpp         |  3 ++
 llvm/include/llvm/TargetParser/Triple.h       | 28 +++++++++++++------
 llvm/lib/Target/Hexagon/HexagonSubtarget.h    |  2 +-
 .../MCTargetDesc/LoongArchBaseInfo.cpp        |  2 ++
 llvm/lib/TargetParser/Triple.cpp              |  8 ++++++
 8 files changed, 41 insertions(+), 13 deletions(-)

diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 281aebdb1c35d..ad83c26cbafbb 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -124,8 +124,7 @@ std::unique_ptr<TargetInfo> AllocateTarget(const 
llvm::Triple &Triple,
     return std::make_unique<XCoreTargetInfo>(Triple, Opts);
 
   case llvm::Triple::hexagon:
-    if (os == llvm::Triple::Linux &&
-        Triple.getEnvironment() == llvm::Triple::Musl)
+    if (os == llvm::Triple::Linux && Triple.isMusl())
       return std::make_unique<LinuxTargetInfo<HexagonTargetInfo>>(Triple, 
Opts);
     return std::make_unique<HexagonTargetInfo>(Triple, Opts);
 
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index eca96c1cce7f7..da8f573621929 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -796,8 +796,7 @@ static llvm::Triple computeTargetTriple(const Driver &D,
             Target.getEnvironment() == llvm::Triple::GNUT64 ||
             Target.getEnvironment() == llvm::Triple::GNUABI64)
           Target.setEnvironment(llvm::Triple::GNUABIN32);
-        else if (Target.getEnvironment() == llvm::Triple::Musl ||
-                 Target.getEnvironment() == llvm::Triple::MuslABI64)
+        else if (Target.isMusl())
           Target.setEnvironment(llvm::Triple::MuslABIN32);
       } else if (ABIName == "64") {
         Target = Target.get64BitArchVariant();
@@ -808,6 +807,9 @@ static llvm::Triple computeTargetTriple(const Driver &D,
         else if (Target.getEnvironment() == llvm::Triple::Musl ||
                  Target.getEnvironment() == llvm::Triple::MuslABIN32)
           Target.setEnvironment(llvm::Triple::MuslABI64);
+        else if (Target.getEnvironment() == llvm::Triple::MuslF128 ||
+                 Target.getEnvironment() == llvm::Triple::MuslABIN3F128)
+          Target.setEnvironment(llvm::Triple::MuslABI64F128);
       }
     }
   }
diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp 
b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
index 0575a1ebef3a6..75f875ab936b1 100644
--- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
@@ -105,9 +105,11 @@ StringRef loongarch::getLoongArchABI(const Driver &D, 
const ArgList &Args,
   switch (Triple.getEnvironment()) {
   case llvm::Triple::GNUSF:
   case llvm::Triple::MuslSF:
+  case llvm::Triple::MuslSFF128:
     return IsLA32 ? "ilp32s" : "lp64s";
   case llvm::Triple::GNUF32:
   case llvm::Triple::MuslF32:
+  case llvm::Triple::MuslF32F128:
     return IsLA32 ? "ilp32f" : "lp64f";
   case llvm::Triple::GNUF64:
     // This was originally permitted (and indeed the canonical way) to
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp 
b/clang/lib/Driver/ToolChains/Linux.cpp
index 1e9bd3de75f04..1bcba0220d531 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -110,15 +110,18 @@ std::string Linux::getMultiarchTriple(const Driver &D,
       return TargetTriple.str();
     case llvm::Triple::GNUSF:
     case llvm::Triple::MuslSF:
+    case llvm::Triple::MuslSFF128:
       FPFlavor = "sf";
       break;
     case llvm::Triple::GNUF32:
     case llvm::Triple::MuslF32:
+    case llvm::Triple::MuslF32F128:
       FPFlavor = "f32";
       break;
     case llvm::Triple::GNU:
     case llvm::Triple::GNUF64:
     case llvm::Triple::Musl:
+    case llvm::Triple::MuslF128:
       // This was going to be "f64" in an earlier Toolchain Conventions
       // revision, but starting from Feb 2023 the F64 ABI variants are
       // unmarked in their canonical forms.
diff --git a/llvm/include/llvm/TargetParser/Triple.h 
b/llvm/include/llvm/TargetParser/Triple.h
index 09c0d223d9b4d..83962adfb5510 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -262,13 +262,21 @@ class Triple {
     EABIHF,
     Android,
     Musl,
-    MuslABIN32,
-    MuslABI64,
-    MuslEABI,
-    MuslEABIHF,
-    MuslF32,
-    MuslSF,
-    MuslX32,
+    MuslABIN32,     // MIPS N32 ABI
+    MuslABI64,      // MIPS N64 ABI
+    MuslEABI,       // Arm32 EABI
+    MuslEABIHF,     // Arm32 EABI + HF
+    MuslF32,        // LoongArch ILP32F/LP64F
+    MuslSF,         // LoongArch ILP32S/LP64S
+    MuslX32,        // Musl using 32-bit ABI on x86_64
+    // Musl with `*f128` math symbols available (e.g. `sqrtf128` rather than
+    // only `sqrtl`). 32-bit musl variants are excluded sin e `*f128` symbols
+    // are required to use `fp128` at all.
+    MuslF128,
+    MuslABI64F128,
+    MuslF32F128,
+    MuslSFF128,
+
     LLVM,
 
     MSVC,
@@ -824,6 +832,10 @@ class Triple {
            getEnvironment() == Triple::MuslF32 ||
            getEnvironment() == Triple::MuslSF ||
            getEnvironment() == Triple::MuslX32 ||
+           getEnvironment() == Triple::MuslF128 ||
+           getEnvironment() == Triple::MuslABI64F128 ||
+           getEnvironment() == Triple::MuslF32F128 ||
+           getEnvironment() == Triple::MuslSFF128 ||
            getEnvironment() == Triple::OpenHOS || isOSLiteOS();
   }
 
@@ -1079,7 +1091,7 @@ class Triple {
   // Tests whether the target is N32.
   bool isABIN32() const {
     EnvironmentType Env = getEnvironment();
-    return Env == Triple::GNUABIN32 || Env == Triple::MuslABIN32;
+    return Env == Triple::GNUABIN32 || Env == Triple::MuslABIN32 ;
   }
 
   /// Tests whether the target is X32.
diff --git a/llvm/lib/Target/Hexagon/HexagonSubtarget.h 
b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
index 41555db4ac662..606bdab37bf93 100644
--- a/llvm/lib/Target/Hexagon/HexagonSubtarget.h
+++ b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
@@ -113,7 +113,7 @@ class HexagonSubtarget : public HexagonGenSubtargetInfo {
 
   const Triple &getTargetTriple() const { return TargetTriple; }
   bool isEnvironmentMusl() const {
-    return TargetTriple.getEnvironment() == Triple::Musl;
+    return TargetTriple.isMusl();
   }
 
   /// getInstrItins - Return the instruction itineraries based on subtarget
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp 
b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
index 03ce004ed33a5..c15ded457bbe3 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
@@ -54,10 +54,12 @@ static ABI getTripleABI(const Triple &TT) {
   switch (TT.getEnvironment()) {
   case llvm::Triple::EnvironmentType::GNUSF:
   case llvm::Triple::EnvironmentType::MuslSF:
+  case llvm::Triple::EnvironmentType::MuslSFF128:
     TripleABI = Is64Bit ? ABI_LP64S : ABI_ILP32S;
     break;
   case llvm::Triple::EnvironmentType::GNUF32:
   case llvm::Triple::EnvironmentType::MuslF32:
+  case llvm::Triple::EnvironmentType::MuslF32F128:
     TripleABI = Is64Bit ? ABI_LP64F : ABI_ILP32F;
     break;
   // Let the fallback case behave like {ILP32,LP64}D.
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index e9e6f130f757c..4bfc5d8609a09 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -361,6 +361,10 @@ StringRef Triple::getEnvironmentTypeName(EnvironmentType 
Kind) {
   case MuslSF:
     return "muslsf";
   case MuslX32: return "muslx32";
+  case MuslF128: return "musl_f128";
+  case MuslABI64F128: return "muslabi64_f128";
+  case MuslF32F128: return "muslf32_f128";
+  case MuslSFF128: return "muslsf_f128";
   case Simulator: return "simulator";
   case Pixel: return "pixel";
   case Vertex: return "vertex";
@@ -733,6 +737,10 @@ static Triple::EnvironmentType parseEnvironment(StringRef 
EnvironmentName) {
       .StartsWith("gnut64", Triple::GNUT64)
       .StartsWith("gnu", Triple::GNU)
       .StartsWith("android", Triple::Android)
+      .StartsWith("muslabi64_f128", Triple::MuslABI64F128)
+      .StartsWith("muslf32_f128", Triple::MuslF32F128)
+      .StartsWith("muslsf_f128", Triple::MuslSFF128)
+      .StartsWith("musl_f128", Triple::MuslF128)
       .StartsWith("muslabin32", Triple::MuslABIN32)
       .StartsWith("muslabi64", Triple::MuslABI64)
       .StartsWith("musleabihf", Triple::MuslEABIHF)

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to