From be93e05c5dd2e8d3b2ad6104af44e6b5c57bdaf2 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sun, 9 Aug 2026 17:10:56 +0200 Subject: [PATCH 1/2] RuntimeLibcalls: Add sincos to the RISCV runtime libcall set Inspection of the glibc sources suggests this is generically available, with the target variance being for long double support. The set of library functions is a large historical mess I'm attempting to untangle. The traditional system had a large set of defaulted calls, but sincos was a case which was explicitly enabled, and I'm assuming riscv just never got around to adding it. It will be easier to reorganize the library functions if synthetic architectural glibc variance is eliminated. Co-authored-by: Claude (Claude-Opus-4.8) --- llvm/include/llvm/IR/RuntimeLibcalls.td | 1 + llvm/test/CodeGen/RISCV/llvm.sincos.ll | 136 ++++++++++++++++++++ llvm/test/CodeGen/RISCV/sincos-expansion.ll | 40 +++--- 3 files changed, 153 insertions(+), 24 deletions(-) create mode 100644 llvm/test/CodeGen/RISCV/llvm.sincos.ll diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index b0d9663cca395..1b504c8de6add 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -3185,6 +3185,7 @@ def RISCVSystemLibrary : SystemRuntimeLibrary, DefaultStackProtector, diff --git a/llvm/test/CodeGen/RISCV/llvm.sincos.ll b/llvm/test/CodeGen/RISCV/llvm.sincos.ll new file mode 100644 index 0000000000000..bb4935ba885ab --- /dev/null +++ b/llvm/test/CodeGen/RISCV/llvm.sincos.ll @@ -0,0 +1,136 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc -mtriple=riscv64-linux-gnu -mattr=+d < %s | FileCheck %s --check-prefix=RV64 +; RUN: llc -mtriple=riscv32-linux-gnu -mattr=+d < %s | FileCheck %s --check-prefix=RV32 + +; Test the llvm.sincos intrinsic lowering to the sincos libcalls, which glibc +; provides (sincosf/sincos/sincosl). RISCV long double is fp128, so f128 uses +; sincosl. + +define { float, float } @test_sincos_f32(float %a) nounwind { +; RV64-LABEL: test_sincos_f32: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: addi a0, sp, 4 +; RV64-NEXT: mv a1, sp +; RV64-NEXT: call sincosf +; RV64-NEXT: flw fa0, 4(sp) +; RV64-NEXT: flw fa1, 0(sp) +; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-NEXT: addi sp, sp, 16 +; RV64-NEXT: ret +; +; RV32-LABEL: test_sincos_f32: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: addi a0, sp, 8 +; RV32-NEXT: addi a1, sp, 4 +; RV32-NEXT: call sincosf +; RV32-NEXT: flw fa0, 8(sp) +; RV32-NEXT: flw fa1, 4(sp) +; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: ret + %result = call { float, float } @llvm.sincos.f32(float %a) + ret { float, float } %result +} + +define { double, double } @test_sincos_f64(double %a) nounwind { +; RV64-LABEL: test_sincos_f64: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -32 +; RV64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-NEXT: addi a0, sp, 16 +; RV64-NEXT: addi a1, sp, 8 +; RV64-NEXT: call sincos +; RV64-NEXT: fld fa0, 16(sp) +; RV64-NEXT: fld fa1, 8(sp) +; RV64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-NEXT: addi sp, sp, 32 +; RV64-NEXT: ret +; +; RV32-LABEL: test_sincos_f64: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -32 +; RV32-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; RV32-NEXT: addi a0, sp, 16 +; RV32-NEXT: addi a1, sp, 8 +; RV32-NEXT: call sincos +; RV32-NEXT: fld fa0, 16(sp) +; RV32-NEXT: fld fa1, 8(sp) +; RV32-NEXT: lw ra, 28(sp) # 4-byte Folded Reload +; RV32-NEXT: addi sp, sp, 32 +; RV32-NEXT: ret + %result = call { double, double } @llvm.sincos.f64(double %a) + ret { double, double } %result +} + +define { fp128, fp128 } @test_sincos_f128(fp128 %a) nounwind { +; RV64-LABEL: test_sincos_f128: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -48 +; RV64-NEXT: sd ra, 40(sp) # 8-byte Folded Spill +; RV64-NEXT: sd s0, 32(sp) # 8-byte Folded Spill +; RV64-NEXT: mv a4, a2 +; RV64-NEXT: mv s0, a0 +; RV64-NEXT: addi a2, sp, 16 +; RV64-NEXT: mv a3, sp +; RV64-NEXT: mv a0, a1 +; RV64-NEXT: mv a1, a4 +; RV64-NEXT: call sincosl +; RV64-NEXT: ld a0, 16(sp) +; RV64-NEXT: ld a1, 24(sp) +; RV64-NEXT: ld a2, 0(sp) +; RV64-NEXT: ld a3, 8(sp) +; RV64-NEXT: sd a0, 0(s0) +; RV64-NEXT: sd a1, 8(s0) +; RV64-NEXT: sd a2, 16(s0) +; RV64-NEXT: sd a3, 24(s0) +; RV64-NEXT: ld ra, 40(sp) # 8-byte Folded Reload +; RV64-NEXT: ld s0, 32(sp) # 8-byte Folded Reload +; RV64-NEXT: addi sp, sp, 48 +; RV64-NEXT: ret +; +; RV32-LABEL: test_sincos_f128: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -80 +; RV32-NEXT: sw ra, 76(sp) # 4-byte Folded Spill +; RV32-NEXT: sw s0, 72(sp) # 4-byte Folded Spill +; RV32-NEXT: lw a4, 0(a1) +; RV32-NEXT: lw a5, 4(a1) +; RV32-NEXT: lw a6, 8(a1) +; RV32-NEXT: lw a7, 12(a1) +; RV32-NEXT: mv s0, a0 +; RV32-NEXT: addi a0, sp, 24 +; RV32-NEXT: addi a1, sp, 8 +; RV32-NEXT: addi a2, sp, 56 +; RV32-NEXT: addi a3, sp, 40 +; RV32-NEXT: sw a4, 8(sp) +; RV32-NEXT: sw a5, 12(sp) +; RV32-NEXT: sw a6, 16(sp) +; RV32-NEXT: sw a7, 20(sp) +; RV32-NEXT: call sincosl +; RV32-NEXT: lw a0, 40(sp) +; RV32-NEXT: lw a1, 44(sp) +; RV32-NEXT: lw a2, 48(sp) +; RV32-NEXT: lw a3, 52(sp) +; RV32-NEXT: lw a4, 56(sp) +; RV32-NEXT: lw a5, 60(sp) +; RV32-NEXT: lw a6, 64(sp) +; RV32-NEXT: lw a7, 68(sp) +; RV32-NEXT: sw a0, 16(s0) +; RV32-NEXT: sw a1, 20(s0) +; RV32-NEXT: sw a2, 24(s0) +; RV32-NEXT: sw a3, 28(s0) +; RV32-NEXT: sw a4, 0(s0) +; RV32-NEXT: sw a5, 4(s0) +; RV32-NEXT: sw a6, 8(s0) +; RV32-NEXT: sw a7, 12(s0) +; RV32-NEXT: lw ra, 76(sp) # 4-byte Folded Reload +; RV32-NEXT: lw s0, 72(sp) # 4-byte Folded Reload +; RV32-NEXT: addi sp, sp, 80 +; RV32-NEXT: ret + %result = call { fp128, fp128 } @llvm.sincos.f128(fp128 %a) + ret { fp128, fp128 } %result +} diff --git a/llvm/test/CodeGen/RISCV/sincos-expansion.ll b/llvm/test/CodeGen/RISCV/sincos-expansion.ll index 6f37d67134cb3..606768a8e2f53 100644 --- a/llvm/test/CodeGen/RISCV/sincos-expansion.ll +++ b/llvm/test/CodeGen/RISCV/sincos-expansion.ll @@ -7,20 +7,16 @@ define float @test_sincos_f32(float %f) nounwind { ; CHECK-LABEL: test_sincos_f32: ; CHECK: # %bb.0: -; CHECK-NEXT: addi sp, sp, -32 -; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill -; CHECK-NEXT: fsd fs0, 16(sp) # 8-byte Folded Spill -; CHECK-NEXT: fsd fs1, 8(sp) # 8-byte Folded Spill -; CHECK-NEXT: fmv.s fs0, fa0 -; CHECK-NEXT: call sinf -; CHECK-NEXT: fmv.s fs1, fa0 -; CHECK-NEXT: fmv.s fa0, fs0 -; CHECK-NEXT: call cosf -; CHECK-NEXT: fadd.s fa0, fs1, fa0 -; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload -; CHECK-NEXT: fld fs0, 16(sp) # 8-byte Folded Reload -; CHECK-NEXT: fld fs1, 8(sp) # 8-byte Folded Reload -; CHECK-NEXT: addi sp, sp, 32 +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: addi a0, sp, 4 +; CHECK-NEXT: mv a1, sp +; CHECK-NEXT: call sincosf +; CHECK-NEXT: flw fa5, 0(sp) +; CHECK-NEXT: flw fa4, 4(sp) +; CHECK-NEXT: fadd.s fa0, fa4, fa5 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret %sin = call float @sinf(float %f) readnone %cos = call float @cosf(float %f) readnone @@ -57,17 +53,13 @@ define double @test_sincos_f64(double %f) nounwind { ; CHECK: # %bb.0: ; CHECK-NEXT: addi sp, sp, -32 ; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill -; CHECK-NEXT: fsd fs0, 16(sp) # 8-byte Folded Spill -; CHECK-NEXT: fsd fs1, 8(sp) # 8-byte Folded Spill -; CHECK-NEXT: fmv.d fs0, fa0 -; CHECK-NEXT: call sin -; CHECK-NEXT: fmv.d fs1, fa0 -; CHECK-NEXT: fmv.d fa0, fs0 -; CHECK-NEXT: call cos -; CHECK-NEXT: fadd.d fa0, fs1, fa0 +; CHECK-NEXT: addi a0, sp, 16 +; CHECK-NEXT: addi a1, sp, 8 +; CHECK-NEXT: call sincos +; CHECK-NEXT: fld fa5, 8(sp) +; CHECK-NEXT: fld fa4, 16(sp) +; CHECK-NEXT: fadd.d fa0, fa4, fa5 ; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload -; CHECK-NEXT: fld fs0, 16(sp) # 8-byte Folded Reload -; CHECK-NEXT: fld fs1, 8(sp) # 8-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 32 ; CHECK-NEXT: ret %sin = call double @sin(double %f) readnone From 9ee4dd845809b32c0ef2af315505cb311c85cf35 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 10 Aug 2026 18:31:48 +0200 Subject: [PATCH 2/2] spelling Co-authored-by: Craig Topper --- llvm/test/CodeGen/RISCV/llvm.sincos.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/CodeGen/RISCV/llvm.sincos.ll b/llvm/test/CodeGen/RISCV/llvm.sincos.ll index bb4935ba885ab..9c7254729008d 100644 --- a/llvm/test/CodeGen/RISCV/llvm.sincos.ll +++ b/llvm/test/CodeGen/RISCV/llvm.sincos.ll @@ -3,7 +3,7 @@ ; RUN: llc -mtriple=riscv32-linux-gnu -mattr=+d < %s | FileCheck %s --check-prefix=RV32 ; Test the llvm.sincos intrinsic lowering to the sincos libcalls, which glibc -; provides (sincosf/sincos/sincosl). RISCV long double is fp128, so f128 uses +; provides (sincosf/sincos/sincosl). RISC-V long double is fp128, so f128 uses ; sincosl. define { float, float } @test_sincos_f32(float %a) nounwind {