[llvm] [CodeGen] Lower vector llvm.sincos to AMDLIBM vector calls (PR #194580)

Kito Cheng via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 28 23:26:39 PDT 2026


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

>From d2acbb523b8bd64ba3f2ade44ec6cc053e7363ac Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng at sifive.com>
Date: Tue, 28 Apr 2026 13:18:26 +0800
Subject: [PATCH] [CodeGen] Lower vector llvm.sincos to AMDLIBM vector calls

- Adds amd_vrd2_sincos to RuntimeLibcalls.td.
- Adds v8f32, v16f32, v4f64, and v8f64 cases to getSINCOS().
- Enables the AMDLIBM sincos in RuntimeLibcallsInfo.
---
 llvm/include/llvm/IR/RuntimeLibcalls.td     |   1 +
 llvm/lib/CodeGen/TargetLoweringBase.cpp     |   8 +
 llvm/lib/IR/RuntimeLibcalls.cpp             |   7 +
 llvm/test/CodeGen/X86/veclib-llvm.sincos.ll | 175 ++++++++++++++------
 4 files changed, 137 insertions(+), 54 deletions(-)

diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 28967d81f63fb..a09825dfa43dc 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -4431,6 +4431,7 @@ defset list<RuntimeLibcallImpl> AMDLIBM_VECFUNCS = {
   def amd_vrd2_log2 : RuntimeLibcallImpl<LOG2_V2F64>;
   def amd_vrd2_pow : RuntimeLibcallImpl<POW_V2F64>;
   def amd_vrd2_sin : RuntimeLibcallImpl<SIN_V2F64>;
+  def amd_vrd2_sincos : RuntimeLibcallImpl<SINCOS_V2F64>;
   def amd_vrd2_tan : RuntimeLibcallImpl<TAN_V2F64>;
   def amd_vrd4_atan : RuntimeLibcallImpl<ATAN_V4F64>;
   def amd_vrd4_cos : RuntimeLibcallImpl<COS_V4F64>;
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index ad858dc0c3af6..28826c08cbdec 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -586,8 +586,16 @@ RTLIB::Libcall RTLIB::getSINCOS(EVT RetVT) {
     switch (RetVT.getSimpleVT().SimpleTy) {
     case MVT::v4f32:
       return RTLIB::SINCOS_V4F32;
+    case MVT::v8f32:
+      return RTLIB::SINCOS_V8F32;
+    case MVT::v16f32:
+      return RTLIB::SINCOS_V16F32;
     case MVT::v2f64:
       return RTLIB::SINCOS_V2F64;
+    case MVT::v4f64:
+      return RTLIB::SINCOS_V4F64;
+    case MVT::v8f64:
+      return RTLIB::SINCOS_V8F64;
     case MVT::nxv4f32:
       return RTLIB::SINCOS_NXV4F32;
     case MVT::nxv2f64:
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index 96aef02342612..d72277fa2b179 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -89,6 +89,13 @@ RuntimeLibcallsInfo::RuntimeLibcallsInfo(const Triple &TT,
           RTLIB::impl_armpl_vcbrtq_f32, RTLIB::impl_armpl_vcbrtq_f64})
       setLibcallImplCallingConv(Impl, CallingConv::AArch64_VectorCall);
     break;
+  case VectorLibrary::AMDLIBM:
+    for (RTLIB::LibcallImpl Impl :
+         {RTLIB::impl_amd_vrd2_sincos, RTLIB::impl_amd_vrd4_sincos,
+          RTLIB::impl_amd_vrd8_sincos, RTLIB::impl_amd_vrs4_sincosf,
+          RTLIB::impl_amd_vrs8_sincosf, RTLIB::impl_amd_vrs16_sincosf})
+      setAvailable(Impl);
+    break;
   default:
     break;
   }
diff --git a/llvm/test/CodeGen/X86/veclib-llvm.sincos.ll b/llvm/test/CodeGen/X86/veclib-llvm.sincos.ll
index 11bc122cb80c8..0075e85865667 100644
--- a/llvm/test/CodeGen/X86/veclib-llvm.sincos.ll
+++ b/llvm/test/CodeGen/X86/veclib-llvm.sincos.ll
@@ -9,11 +9,14 @@
 ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mcpu=x86-64-v4 -vector-library=LIBMVEC < %s | FileCheck %s --check-prefixes=CHECK,GLIBC,GLIBC-AVX512
 
 define void @test_sincos_v4f32(<4 x float> %x, ptr noalias %out_sin, ptr noalias %out_cos) {
-; CHECK-LABEL: test_sincos_v4f32:
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
+; AMD-LABEL: test_sincos_v4f32:
+; 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
   %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
@@ -23,15 +26,29 @@ define void @test_sincos_v4f32(<4 x float> %x, ptr noalias %out_sin, ptr noalias
 }
 
 define void @test_sincos_v8f32(<8 x float> %x, ptr noalias %out_sin, ptr noalias %out_cos) {
-; CHECK-LABEL: test_sincos_v8f32:
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
+; AMD-SSE-LABEL: test_sincos_v8f32:
+; AMD-SSE:    callq amd_vrs4_sincosf at PLT
+; AMD-SSE:    callq amd_vrs4_sincosf at PLT
+;
+; AMD-AVX-LABEL: test_sincos_v8f32:
+; AMD-AVX:    callq amd_vrs4_sincosf at PLT
+; AMD-AVX:    callq amd_vrs4_sincosf at PLT
+;
+; AMD-AVX2-LABEL: test_sincos_v8f32:
+; AMD-AVX2:    callq amd_vrs8_sincosf at PLT
+;
+; AMD-AVX512-LABEL: test_sincos_v8f32:
+; 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
   %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
@@ -41,23 +58,42 @@ define void @test_sincos_v8f32(<8 x float> %x, ptr noalias %out_sin, ptr noalias
 }
 
 define void @test_sincos_v16f32(<16 x float> %x, ptr noalias %out_sin, ptr noalias %out_cos) {
-; CHECK-LABEL: test_sincos_v16f32:
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
-; CHECK:    callq sincosf at PLT
+; AMD-SSE-LABEL: test_sincos_v16f32:
+; AMD-SSE:    callq amd_vrs4_sincosf at PLT
+; AMD-SSE:    callq amd_vrs4_sincosf at PLT
+; AMD-SSE:    callq amd_vrs4_sincosf at PLT
+; AMD-SSE:    callq amd_vrs4_sincosf at PLT
+;
+; AMD-AVX-LABEL: test_sincos_v16f32:
+; AMD-AVX:    callq amd_vrs4_sincosf at PLT
+; AMD-AVX:    callq amd_vrs4_sincosf at PLT
+; AMD-AVX:    callq amd_vrs4_sincosf at PLT
+; AMD-AVX:    callq amd_vrs4_sincosf at PLT
+;
+; AMD-AVX2-LABEL: test_sincos_v16f32:
+; AMD-AVX2:    callq amd_vrs8_sincosf at PLT
+; AMD-AVX2:    callq amd_vrs8_sincosf at PLT
+;
+; AMD-AVX512-LABEL: test_sincos_v16f32:
+; AMD-AVX512:    callq amd_vrs16_sincosf at PLT
+;
+; GLIBC-LABEL: test_sincos_v16f32:
+; 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 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
   %result = call { <16 x float>, <16 x float> } @llvm.sincos.v16f32(<16 x float> %x)
   %result.0 = extractvalue { <16 x float>, <16 x float> } %result, 0
   %result.1 = extractvalue { <16 x float>, <16 x float> } %result, 1
@@ -67,9 +103,12 @@ define void @test_sincos_v16f32(<16 x float> %x, ptr noalias %out_sin, ptr noali
 }
 
 define void @test_sincos_v2f64(<2 x double> %x, ptr noalias %out_sin, ptr noalias %out_cos) {
-; CHECK-LABEL: test_sincos_v2f64:
-; CHECK:    callq sincos at PLT
-; CHECK:    callq sincos at PLT
+; AMD-LABEL: test_sincos_v2f64:
+; AMD:    callq amd_vrd2_sincos at PLT
+;
+; GLIBC-LABEL: test_sincos_v2f64:
+; GLIBC:    callq sincos at PLT
+; GLIBC:    callq sincos 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
@@ -79,11 +118,25 @@ define void @test_sincos_v2f64(<2 x double> %x, ptr noalias %out_sin, ptr noalia
 }
 
 define void @test_sincos_v4f64(<4 x double> %x, ptr noalias %out_sin, ptr noalias %out_cos) {
-; CHECK-LABEL: test_sincos_v4f64:
-; CHECK:    callq sincos at PLT
-; CHECK:    callq sincos at PLT
-; CHECK:    callq sincos at PLT
-; CHECK:    callq sincos at PLT
+; AMD-SSE-LABEL: test_sincos_v4f64:
+; AMD-SSE:    callq amd_vrd2_sincos at PLT
+; AMD-SSE:    callq amd_vrd2_sincos at PLT
+;
+; AMD-AVX-LABEL: test_sincos_v4f64:
+; AMD-AVX:    callq amd_vrd2_sincos at PLT
+; AMD-AVX:    callq amd_vrd2_sincos at PLT
+;
+; AMD-AVX2-LABEL: test_sincos_v4f64:
+; AMD-AVX2:    callq amd_vrd4_sincos at PLT
+;
+; AMD-AVX512-LABEL: test_sincos_v4f64:
+; 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
   %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
@@ -93,15 +146,34 @@ define void @test_sincos_v4f64(<4 x double> %x, ptr noalias %out_sin, ptr noalia
 }
 
 define void @test_sincos_v8f64(<8 x double> %x, ptr noalias %out_sin, ptr noalias %out_cos) {
-; CHECK-LABEL: test_sincos_v8f64:
-; CHECK:    callq sincos at PLT
-; CHECK:    callq sincos at PLT
-; CHECK:    callq sincos at PLT
-; CHECK:    callq sincos at PLT
-; CHECK:    callq sincos at PLT
-; CHECK:    callq sincos at PLT
-; CHECK:    callq sincos at PLT
-; CHECK:    callq sincos at PLT
+; AMD-SSE-LABEL: test_sincos_v8f64:
+; AMD-SSE:    callq amd_vrd2_sincos at PLT
+; AMD-SSE:    callq amd_vrd2_sincos at PLT
+; AMD-SSE:    callq amd_vrd2_sincos at PLT
+; AMD-SSE:    callq amd_vrd2_sincos at PLT
+;
+; AMD-AVX-LABEL: test_sincos_v8f64:
+; AMD-AVX:    callq amd_vrd2_sincos at PLT
+; AMD-AVX:    callq amd_vrd2_sincos at PLT
+; AMD-AVX:    callq amd_vrd2_sincos at PLT
+; AMD-AVX:    callq amd_vrd2_sincos at PLT
+;
+; AMD-AVX2-LABEL: test_sincos_v8f64:
+; AMD-AVX2:    callq amd_vrd4_sincos at PLT
+; AMD-AVX2:    callq amd_vrd4_sincos at PLT
+;
+; AMD-AVX512-LABEL: test_sincos_v8f64:
+; AMD-AVX512:    callq amd_vrd8_sincos at PLT
+;
+; GLIBC-LABEL: test_sincos_v8f64:
+; GLIBC:    callq sincos at PLT
+; GLIBC:    callq sincos at PLT
+; GLIBC:    callq sincos at PLT
+; GLIBC:    callq sincos at PLT
+; GLIBC:    callq sincos at PLT
+; GLIBC:    callq sincos at PLT
+; GLIBC:    callq sincos at PLT
+; GLIBC:    callq sincos at PLT
   %result = call { <8 x double>, <8 x double> } @llvm.sincos.v8f64(<8 x double> %x)
   %result.0 = extractvalue { <8 x double>, <8 x double> } %result, 0
   %result.1 = extractvalue { <8 x double>, <8 x double> } %result, 1
@@ -110,12 +182,7 @@ define void @test_sincos_v8f64(<8 x double> %x, ptr noalias %out_sin, ptr noalia
   ret void
 }
 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; AMD: {{.*}}
-; AMD-AVX: {{.*}}
-; AMD-AVX2: {{.*}}
-; AMD-AVX512: {{.*}}
-; AMD-SSE: {{.*}}
-; GLIBC: {{.*}}
+; CHECK: {{.*}}
 ; GLIBC-AVX: {{.*}}
 ; GLIBC-AVX2: {{.*}}
 ; GLIBC-AVX512: {{.*}}



More information about the llvm-commits mailing list