[llvm] [CodeGen] Teach ReplaceWithVeclib split vector llvm.sincos when only sin/cos veclib mappings exist (PR #194639)

Kito Cheng via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 14 18:04:54 PDT 2026


https://github.com/kito-cheng updated https://github.com/llvm/llvm-project/pull/194639

>From 092b52207d1e99785c2ccd49bc1bb46bbaee80f2 Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng at sifive.com>
Date: Tue, 28 Apr 2026 15:00:13 +0800
Subject: [PATCH 1/6] [CodeGen] Teach ReplaceWithVeclib split vector
 llvm.sincos when only sin/cos veclib mappings exist

Some vector math libraries provide vector sin and vector cos but no vector
sincos or no sincos with an ABI that LLVM can emit.

The one of the common case is glibc libmvec on x86: it exposes
`_ZGV{b,c,d,e}N{2,4,8,16}vvv_sincos{,f}` symbols, but those use a
vectors-of-pointers output ABI that expandMultipleResultFPLibCall does
not currently support. As a result, sincos will falls back to scalar sincos
calls even when the target has a fully working vector sin and vector cos.

So we trying to split it into separate sin and cos calls, which will
then be replaced with vector calls if the target supports it, it
generally better than scalarized sincos calls.
---
 llvm/lib/CodeGen/ReplaceWithVeclib.cpp | 115 +++++++++++++++++++++++--
 1 file changed, 106 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
index 600b8d84e3926..2dd71ba75c4b4 100644
--- a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
+++ b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
@@ -207,19 +207,116 @@ static bool replaceWithCallToVeclib(const TargetLibraryInfo &TLI,
   return true;
 }
 
+/// Returns true when \p TLI has a vector mapping for the scalar function name
+/// \p Name at \p EC (matching either masked or unmasked variants).
+static bool hasVectorMapping(const TargetLibraryInfo &TLI, StringRef Name,
+                             ElementCount EC) {
+  return TLI.getVectorMappingInfo(Name, EC, /*Masked=*/false) ||
+         TLI.getVectorMappingInfo(Name, EC, /*Masked=*/true);
+}
+
+/// Returns true when \p TLI has a vector mapping for \p IID at the given
+/// element type and \p EC.
+static bool hasIntrinsicVectorMapping(const TargetLibraryInfo &TLI,
+                                      Intrinsic::ID IID, Type *ScalarTy,
+                                      ElementCount EC, Module *M) {
+  std::string Name = Intrinsic::getName(IID, {ScalarTy}, M);
+  return hasVectorMapping(TLI, Name, EC);
+}
+
+/// If \p II is a vector llvm.sincos with no direct vector library mapping but
+/// the target does have vector mappings for both llvm.sin and llvm.cos at the
+/// same element count, replace it with separate llvm.sin and llvm.cos calls
+/// and run the standard veclib replacement on each.
+static bool trySplitVectorSinCos(const TargetLibraryInfo &TLI,
+                                 IntrinsicInst *II,
+                                 SmallVectorImpl<Instruction *> &Replaced) {
+  if (II->getIntrinsicID() != Intrinsic::sincos)
+    return false;
+  Value *Arg = II->getArgOperand(0);
+  auto *VTy = dyn_cast<VectorType>(Arg->getType());
+  if (!VTy)
+    return false;
+
+  ElementCount EC = VTy->getElementCount();
+  Type *ScalarTy = VTy->getElementType();
+  Module *M = II->getModule();
+
+  // If a vector sincos mapping exists for the intrinsic name (e.g.
+  // "llvm.sincos.f32") or for the scalar libcall name ("sincos"/"sincosf"),
+  // leave the call alone -- SelectionDAG legalization will handle it via
+  // expandMultipleResultFPLibCall when the runtime libcall impl is enabled.
+  if (hasIntrinsicVectorMapping(TLI, Intrinsic::sincos, ScalarTy, EC, M))
+    return false;
+  StringRef LibcallName;
+  if (ScalarTy->isFloatTy())
+    LibcallName = "sincosf";
+  else if (ScalarTy->isDoubleTy())
+    LibcallName = "sincos";
+  if (!LibcallName.empty() && hasVectorMapping(TLI, LibcallName, EC))
+    return false;
+
+  // Splitting is only worthwhile when both sin and cos have vector mappings.
+  if (!hasIntrinsicVectorMapping(TLI, Intrinsic::sin, ScalarTy, EC, M) ||
+      !hasIntrinsicVectorMapping(TLI, Intrinsic::cos, ScalarTy, EC, M))
+    return false;
+
+  // All users must be extractvalue with index 0 or 1; otherwise we cannot
+  // safely rewire results.
+  for (User *U : II->users()) {
+    auto *EV = dyn_cast<ExtractValueInst>(U);
+    if (!EV || EV->getNumIndices() != 1 ||
+        (EV->getIndices()[0] != 0 && EV->getIndices()[0] != 1))
+      return false;
+  }
+
+  IRBuilder<> B(II);
+  Function *SinFn =
+      Intrinsic::getOrInsertDeclaration(M, Intrinsic::sin, Arg->getType());
+  Function *CosFn =
+      Intrinsic::getOrInsertDeclaration(M, Intrinsic::cos, Arg->getType());
+  CallInst *SinCall = B.CreateCall(SinFn, {Arg}, "sin");
+  CallInst *CosCall = B.CreateCall(CosFn, {Arg}, "cos");
+  SinCall->copyFastMathFlags(II);
+  CosCall->copyFastMathFlags(II);
+
+  // Forward extractvalue uses to the new calls.
+  for (User *U : llvm::make_early_inc_range(II->users())) {
+    auto *EV = cast<ExtractValueInst>(U);
+    EV->replaceAllUsesWith(EV->getIndices()[0] == 0 ? SinCall : CosCall);
+    EV->eraseFromParent();
+  }
+
+  // Replace each new call with the vector library function.
+  if (replaceWithCallToVeclib(TLI, cast<IntrinsicInst>(SinCall)))
+    Replaced.push_back(SinCall);
+  if (replaceWithCallToVeclib(TLI, cast<IntrinsicInst>(CosCall)))
+    Replaced.push_back(CosCall);
+
+  return true;
+}
+
 static bool runImpl(const TargetLibraryInfo &TLI, Function &F) {
   SmallVector<Instruction *> ReplacedCalls;
   for (auto &I : instructions(F)) {
-    // Process only intrinsic calls that return void or a vector.
-    if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
-      if (II->getIntrinsicID() == Intrinsic::not_intrinsic)
-        continue;
-      if (!II->getType()->isVectorTy() && !II->getType()->isVoidTy())
-        continue;
-
-      if (replaceWithCallToVeclib(TLI, II))
-        ReplacedCalls.push_back(&I);
+    auto *II = dyn_cast<IntrinsicInst>(&I);
+    if (!II || II->getIntrinsicID() == Intrinsic::not_intrinsic)
+      continue;
+
+    // Vector llvm.sincos returns a struct so it does not fit the generic
+    // path below; try to split it into separate sin and cos calls when the
+    // target has vector mappings for them.
+    if (trySplitVectorSinCos(TLI, II, ReplacedCalls)) {
+      ReplacedCalls.push_back(&I);
+      continue;
     }
+
+    // Process only intrinsic calls that return void or a vector.
+    if (!II->getType()->isVectorTy() && !II->getType()->isVoidTy())
+      continue;
+
+    if (replaceWithCallToVeclib(TLI, II))
+      ReplacedCalls.push_back(&I);
   }
   // Erase any intrinsic calls that were replaced with vector library calls.
   for (auto *I : ReplacedCalls)

>From 61649825c2499eef491f66ebd64378d4fb8fd311 Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng at sifive.com>
Date: Mon, 4 May 2026 15:29:05 +0800
Subject: [PATCH 2/6] fixup! [CodeGen] Teach ReplaceWithVeclib split vector
 llvm.sincos when only sin/cos veclib mappings exist

---
 llvm/lib/CodeGen/ReplaceWithVeclib.cpp | 19 +++++----
 llvm/test/CodeGen/X86/sincos-fpmath.ll | 56 ++++++++++++++++++++++++++
 2 files changed, 65 insertions(+), 10 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/sincos-fpmath.ll

diff --git a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
index 2dd71ba75c4b4..55722d6d8804b 100644
--- a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
+++ b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
@@ -248,12 +248,12 @@ static bool trySplitVectorSinCos(const TargetLibraryInfo &TLI,
   // expandMultipleResultFPLibCall when the runtime libcall impl is enabled.
   if (hasIntrinsicVectorMapping(TLI, Intrinsic::sincos, ScalarTy, EC, M))
     return false;
-  StringRef LibcallName;
+  LibFunc LF = NotLibFunc;
   if (ScalarTy->isFloatTy())
-    LibcallName = "sincosf";
+    LF = LibFunc_sincosf;
   else if (ScalarTy->isDoubleTy())
-    LibcallName = "sincos";
-  if (!LibcallName.empty() && hasVectorMapping(TLI, LibcallName, EC))
+    LF = LibFunc_sincos;
+  if (LF != NotLibFunc && hasVectorMapping(TLI, TLI.getName(LF), EC))
     return false;
 
   // Splitting is only worthwhile when both sin and cos have vector mappings.
@@ -261,12 +261,9 @@ static bool trySplitVectorSinCos(const TargetLibraryInfo &TLI,
       !hasIntrinsicVectorMapping(TLI, Intrinsic::cos, ScalarTy, EC, M))
     return false;
 
-  // All users must be extractvalue with index 0 or 1; otherwise we cannot
-  // safely rewire results.
+  // All users must be extractvalue.
   for (User *U : II->users()) {
-    auto *EV = dyn_cast<ExtractValueInst>(U);
-    if (!EV || EV->getNumIndices() != 1 ||
-        (EV->getIndices()[0] != 0 && EV->getIndices()[0] != 1))
+    if (!isa<ExtractValueInst>(U))
       return false;
   }
 
@@ -279,9 +276,11 @@ static bool trySplitVectorSinCos(const TargetLibraryInfo &TLI,
   CallInst *CosCall = B.CreateCall(CosFn, {Arg}, "cos");
   SinCall->copyFastMathFlags(II);
   CosCall->copyFastMathFlags(II);
+  SinCall->copyMetadata(*II, {LLVMContext::MD_fpmath});
+  CosCall->copyMetadata(*II, {LLVMContext::MD_fpmath});
 
   // Forward extractvalue uses to the new calls.
-  for (User *U : llvm::make_early_inc_range(II->users())) {
+  for (User *U : make_early_inc_range(II->users())) {
     auto *EV = cast<ExtractValueInst>(U);
     EV->replaceAllUsesWith(EV->getIndices()[0] == 0 ? SinCall : CosCall);
     EV->eraseFromParent();
diff --git a/llvm/test/CodeGen/X86/sincos-fpmath.ll b/llvm/test/CodeGen/X86/sincos-fpmath.ll
new file mode 100644
index 0000000000000..c50b8832c0013
--- /dev/null
+++ b/llvm/test/CodeGen/X86/sincos-fpmath.ll
@@ -0,0 +1,56 @@
+; RUN: opt -mtriple=x86_64-unknown-linux-gnu -vector-library=LIBMVEC -passes=replace-with-veclib -S < %s | FileCheck %s
+
+declare { <4 x float>, <4 x float> } @llvm.sincos.v4f32(<4 x float>)
+declare { <2 x double>, <2 x double> } @llvm.sincos.v2f64(<2 x double>)
+
+; v4f32 sincos -> _ZGVbN4v_sinf / _ZGVbN4v_cosf, both carrying !fpmath !0.
+define void @sincos_fpmath_v4f32(<4 x float> %x, ptr noalias %sin_out, ptr noalias %cos_out) {
+; CHECK-LABEL: @sincos_fpmath_v4f32(
+; CHECK:         call <4 x float> @_ZGVbN4v_sinf(<4 x float> %x), !fpmath !0
+; CHECK:         call <4 x float> @_ZGVbN4v_cosf(<4 x float> %x), !fpmath !0
+;
+  %r = call { <4 x float>, <4 x float> } @llvm.sincos.v4f32(<4 x float> %x), !fpmath !0
+  %s = extractvalue { <4 x float>, <4 x float> } %r, 0
+  %c = extractvalue { <4 x float>, <4 x float> } %r, 1
+  store <4 x float> %s, ptr %sin_out, align 16
+  store <4 x float> %c, ptr %cos_out, align 16
+  ret void
+}
+
+; v2f64 sincos -> _ZGVbN2v_sin / _ZGVbN2v_cos, both carrying !fpmath !1.
+define void @sincos_fpmath_v2f64(<2 x double> %x, ptr noalias %sin_out, ptr noalias %cos_out) {
+; CHECK-LABEL: @sincos_fpmath_v2f64(
+; CHECK:         call <2 x double> @_ZGVbN2v_sin(<2 x double> %x), !fpmath !1
+; CHECK:         call <2 x double> @_ZGVbN2v_cos(<2 x double> %x), !fpmath !1
+;
+  %r = call { <2 x double>, <2 x double> } @llvm.sincos.v2f64(<2 x double> %x), !fpmath !1
+  %s = extractvalue { <2 x double>, <2 x double> } %r, 0
+  %c = extractvalue { <2 x double>, <2 x double> } %r, 1
+  store <2 x double> %s, ptr %sin_out, align 16
+  store <2 x double> %c, ptr %cos_out, align 16
+  ret void
+}
+
+; When the original sincos has no fpmath metadata, the resulting vector sin
+; and cos calls should also have none.
+define void @sincos_no_fpmath_v4f32(<4 x float> %x, ptr noalias %sin_out, ptr noalias %cos_out) {
+; CHECK-LABEL: @sincos_no_fpmath_v4f32(
+; CHECK:         call <4 x float> @_ZGVbN4v_sinf(<4 x float> %x){{$}}
+; CHECK-NOT:     !fpmath
+; CHECK:         call <4 x float> @_ZGVbN4v_cosf(<4 x float> %x){{$}}
+; CHECK-NOT:     !fpmath
+;
+  %r = call { <4 x float>, <4 x float> } @llvm.sincos.v4f32(<4 x float> %x)
+  %s = extractvalue { <4 x float>, <4 x float> } %r, 0
+  %c = extractvalue { <4 x float>, <4 x float> } %r, 1
+  store <4 x float> %s, ptr %sin_out, align 16
+  store <4 x float> %c, ptr %cos_out, align 16
+  ret void
+}
+
+; Verify the exact !fpmath metadata values are preserved.
+; CHECK: !0 = !{float 2.500000e+00}
+; CHECK: !1 = !{float 4.000000e+00}
+
+!0 = !{float 2.5}
+!1 = !{float 4.0}

>From 330641006ee4dd092413fdbe7b38f246161e84b8 Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng at sifive.com>
Date: Wed, 20 May 2026 15:29:09 +0800
Subject: [PATCH 3/6] !fixup drop check II->getIntrinsicID() ==
 Intrinsic::not_intrinsic

---
 llvm/lib/CodeGen/ReplaceWithVeclib.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
index 55722d6d8804b..8ec29313c9398 100644
--- a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
+++ b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
@@ -299,7 +299,7 @@ static bool runImpl(const TargetLibraryInfo &TLI, Function &F) {
   SmallVector<Instruction *> ReplacedCalls;
   for (auto &I : instructions(F)) {
     auto *II = dyn_cast<IntrinsicInst>(&I);
-    if (!II || II->getIntrinsicID() == Intrinsic::not_intrinsic)
+    if (!II)
       continue;
 
     // Vector llvm.sincos returns a struct so it does not fit the generic

>From 1348bf99b7fe8bb58b1d496f69678d5ed466b969 Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng at sifive.com>
Date: Wed, 8 Jul 2026 13:52:57 +0800
Subject: [PATCH 4/6] fixup! [CodeGen] Teach ReplaceWithVeclib split vector
 llvm.sincos when only sin/cos veclib mappings exist

---
 llvm/test/CodeGen/X86/sincos-fpmath.ll | 31 ++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/llvm/test/CodeGen/X86/sincos-fpmath.ll b/llvm/test/CodeGen/X86/sincos-fpmath.ll
index c50b8832c0013..8308e0fb7834c 100644
--- a/llvm/test/CodeGen/X86/sincos-fpmath.ll
+++ b/llvm/test/CodeGen/X86/sincos-fpmath.ll
@@ -2,6 +2,8 @@
 
 declare { <4 x float>, <4 x float> } @llvm.sincos.v4f32(<4 x float>)
 declare { <2 x double>, <2 x double> } @llvm.sincos.v2f64(<2 x double>)
+declare { <3 x float>, <3 x float> } @llvm.sincos.v3f32(<3 x float>)
+declare void @use_sincos_struct({ <4 x float>, <4 x float> })
 
 ; v4f32 sincos -> _ZGVbN4v_sinf / _ZGVbN4v_cosf, both carrying !fpmath !0.
 define void @sincos_fpmath_v4f32(<4 x float> %x, ptr noalias %sin_out, ptr noalias %cos_out) {
@@ -48,6 +50,35 @@ define void @sincos_no_fpmath_v4f32(<4 x float> %x, ptr noalias %sin_out, ptr no
   ret void
 }
 
+; A non-extractvalue user blocks the split, so llvm.sincos is left intact.
+define void @sincos_non_extractvalue_user_v4f32(<4 x float> %x, ptr noalias %sin_out) {
+; CHECK-LABEL: @sincos_non_extractvalue_user_v4f32(
+; CHECK:         call { <4 x float>, <4 x float> } @llvm.sincos.v4f32(<4 x float> %x)
+; CHECK-NOT:     _ZGV
+; CHECK:         ret void
+;
+  %r = call { <4 x float>, <4 x float> } @llvm.sincos.v4f32(<4 x float> %x)
+  call void @use_sincos_struct({ <4 x float>, <4 x float> } %r)
+  %s = extractvalue { <4 x float>, <4 x float> } %r, 0
+  store <4 x float> %s, ptr %sin_out, align 16
+  ret void
+}
+
+; An odd vector width has no LIBMVEC sin/cos mapping, so llvm.sincos is left intact.
+define void @sincos_no_veclib_mapping_v3f32(<3 x float> %x, ptr noalias %sin_out, ptr noalias %cos_out) {
+; CHECK-LABEL: @sincos_no_veclib_mapping_v3f32(
+; CHECK:         call { <3 x float>, <3 x float> } @llvm.sincos.v3f32(<3 x float> %x)
+; CHECK-NOT:     _ZGV
+; CHECK:         ret void
+;
+  %r = call { <3 x float>, <3 x float> } @llvm.sincos.v3f32(<3 x float> %x)
+  %s = extractvalue { <3 x float>, <3 x float> } %r, 0
+  %c = extractvalue { <3 x float>, <3 x float> } %r, 1
+  store <3 x float> %s, ptr %sin_out, align 16
+  store <3 x float> %c, ptr %cos_out, align 16
+  ret void
+}
+
 ; Verify the exact !fpmath metadata values are preserved.
 ; CHECK: !0 = !{float 2.500000e+00}
 ; CHECK: !1 = !{float 4.000000e+00}

>From 9e621612980e11f1dc2e4f305b84f2af2c06b511 Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng at sifive.com>
Date: Fri, 10 Jul 2026 17:33:42 +0800
Subject: [PATCH 5/6] fixup Rebase

---
 llvm/lib/CodeGen/ReplaceWithVeclib.cpp      | 10 ++++----
 llvm/test/CodeGen/X86/veclib-llvm.sincos.ll | 26 +++++++--------------
 2 files changed, 14 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
index 8ec29313c9398..bd7b39eb26c34 100644
--- a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
+++ b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
@@ -94,6 +94,10 @@ static void replaceWithTLIFunction(IntrinsicInst *II, VFInfo &Info,
   // safe for non-FP intrinsics, whose flags are simply empty).
   auto *Replacement = IRBuilder.CreateCall(
       TLIVecFunc, Args, OpBundles, /*FMFSource=*/II->getFastMathFlagsOrNone());
+  // Preserve fpmath for FP math
+  if (isa<FPMathOperator>(Replacement)) {
+    Replacement->copyMetadata(*II, {LLVMContext::MD_fpmath});
+  }
   II->replaceAllUsesWith(Replacement);
   Replacement->setCallingConv(TLIVecFunc->getCallingConv());
 }
@@ -272,10 +276,8 @@ static bool trySplitVectorSinCos(const TargetLibraryInfo &TLI,
       Intrinsic::getOrInsertDeclaration(M, Intrinsic::sin, Arg->getType());
   Function *CosFn =
       Intrinsic::getOrInsertDeclaration(M, Intrinsic::cos, Arg->getType());
-  CallInst *SinCall = B.CreateCall(SinFn, {Arg}, "sin");
-  CallInst *CosCall = B.CreateCall(CosFn, {Arg}, "cos");
-  SinCall->copyFastMathFlags(II);
-  CosCall->copyFastMathFlags(II);
+  CallInst *SinCall = B.CreateCall(SinFn, {Arg}, /*FMFSource=*/II, "sin");
+  CallInst *CosCall = B.CreateCall(CosFn, {Arg}, /*FMFSource=*/II, "cos");
   SinCall->copyMetadata(*II, {LLVMContext::MD_fpmath});
   CosCall->copyMetadata(*II, {LLVMContext::MD_fpmath});
 
diff --git a/llvm/test/CodeGen/X86/veclib-llvm.sincos.ll b/llvm/test/CodeGen/X86/veclib-llvm.sincos.ll
index 0075e85865667..b7ce01cfe5622 100644
--- a/llvm/test/CodeGen/X86/veclib-llvm.sincos.ll
+++ b/llvm/test/CodeGen/X86/veclib-llvm.sincos.ll
@@ -13,10 +13,8 @@ define void @test_sincos_v4f32(<4 x float> %x, ptr noalias %out_sin, ptr noalias
 ; AMD:    callq amd_vrs4_sincosf at PLT
 ;
 ; GLIBC-LABEL: test_sincos_v4f32:
-; GLIBC:    callq sincosf at PLT
-; GLIBC:    callq sincosf at PLT
-; GLIBC:    callq sincosf at PLT
-; GLIBC:    callq sincosf at PLT
+; GLIBC:    callq _ZGVbN4v_sinf at PLT
+; GLIBC:    callq _ZGVbN4v_cosf at PLT
   %result = call { <4 x float>, <4 x float> } @llvm.sincos.v4f32(<4 x float> %x)
   %result.0 = extractvalue { <4 x float>, <4 x float> } %result, 0
   %result.1 = extractvalue { <4 x float>, <4 x float> } %result, 1
@@ -41,14 +39,8 @@ define void @test_sincos_v8f32(<8 x float> %x, ptr noalias %out_sin, ptr noalias
 ; AMD-AVX512:    callq amd_vrs8_sincosf at PLT
 ;
 ; GLIBC-LABEL: test_sincos_v8f32:
-; GLIBC:    callq sincosf at PLT
-; GLIBC:    callq sincosf at PLT
-; GLIBC:    callq sincosf at PLT
-; GLIBC:    callq sincosf at PLT
-; GLIBC:    callq sincosf at PLT
-; GLIBC:    callq sincosf at PLT
-; GLIBC:    callq sincosf at PLT
-; GLIBC:    callq sincosf at PLT
+; GLIBC:    callq _ZGVdN8v_sinf at PLT
+; GLIBC:    callq _ZGVdN8v_cosf at PLT
   %result = call { <8 x float>, <8 x float> } @llvm.sincos.v8f32(<8 x float> %x)
   %result.0 = extractvalue { <8 x float>, <8 x float> } %result, 0
   %result.1 = extractvalue { <8 x float>, <8 x float> } %result, 1
@@ -107,8 +99,8 @@ define void @test_sincos_v2f64(<2 x double> %x, ptr noalias %out_sin, ptr noalia
 ; AMD:    callq amd_vrd2_sincos at PLT
 ;
 ; GLIBC-LABEL: test_sincos_v2f64:
-; GLIBC:    callq sincos at PLT
-; GLIBC:    callq sincos at PLT
+; GLIBC:    callq _ZGVbN2v_sin at PLT
+; GLIBC:    callq _ZGVbN2v_cos at PLT
   %result = call { <2 x double>, <2 x double> } @llvm.sincos.v2f64(<2 x double> %x)
   %result.0 = extractvalue { <2 x double>, <2 x double> } %result, 0
   %result.1 = extractvalue { <2 x double>, <2 x double> } %result, 1
@@ -133,10 +125,8 @@ define void @test_sincos_v4f64(<4 x double> %x, ptr noalias %out_sin, ptr noalia
 ; AMD-AVX512:    callq amd_vrd4_sincos at PLT
 ;
 ; GLIBC-LABEL: test_sincos_v4f64:
-; GLIBC:    callq sincos at PLT
-; GLIBC:    callq sincos at PLT
-; GLIBC:    callq sincos at PLT
-; GLIBC:    callq sincos at PLT
+; GLIBC:    callq _ZGVdN4v_sin at PLT
+; GLIBC:    callq _ZGVdN4v_cos at PLT
   %result = call { <4 x double>, <4 x double> } @llvm.sincos.v4f64(<4 x double> %x)
   %result.0 = extractvalue { <4 x double>, <4 x double> } %result, 0
   %result.1 = extractvalue { <4 x double>, <4 x double> } %result, 1

>From ac2f52591153dc692b511de7b79a04903a035b10 Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng at sifive.com>
Date: Wed, 15 Jul 2026 09:03:57 +0800
Subject: [PATCH 6/6] fixup

---
 llvm/lib/CodeGen/ReplaceWithVeclib.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
index bd7b39eb26c34..4a240c914a252 100644
--- a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
+++ b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
@@ -95,9 +95,8 @@ static void replaceWithTLIFunction(IntrinsicInst *II, VFInfo &Info,
   auto *Replacement = IRBuilder.CreateCall(
       TLIVecFunc, Args, OpBundles, /*FMFSource=*/II->getFastMathFlagsOrNone());
   // Preserve fpmath for FP math
-  if (isa<FPMathOperator>(Replacement)) {
+  if (isa<FPMathOperator>(Replacement))
     Replacement->copyMetadata(*II, {LLVMContext::MD_fpmath});
-  }
   II->replaceAllUsesWith(Replacement);
   Replacement->setCallingConv(TLIVecFunc->getCallingConv());
 }



More information about the llvm-commits mailing list