[llvm] [RISCV] Pick correct lround libcall for fp128 (PR #213220)
Kane Wang via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 3 00:17:22 PDT 2026
https://github.com/ReVe1uv updated https://github.com/llvm/llvm-project/pull/213220
>From 16688f281e3cfac9dfe89c607032260ec32f3a12 Mon Sep 17 00:00:00 2001
From: Kane Wang <wangqiang1 at kylinos.cn>
Date: Mon, 3 Aug 2026 15:05:37 +0800
Subject: [PATCH 1/2] [RISCV] Add rv64 coverage to fp128.ll
Add an rv64 RUN line and RV64I checks to fp128.ll so the fp128
libcall lowering is also exercised on rv64. No functional change.
---
llvm/test/CodeGen/RISCV/fp128.ll | 91 ++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/llvm/test/CodeGen/RISCV/fp128.ll b/llvm/test/CodeGen/RISCV/fp128.ll
index 10f5fe9946bb7..a5bcfae678a1a 100644
--- a/llvm/test/CodeGen/RISCV/fp128.ll
+++ b/llvm/test/CodeGen/RISCV/fp128.ll
@@ -1,6 +1,8 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
; RUN: | FileCheck -check-prefix=RV32I %s
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=RV64I %s
@x = local_unnamed_addr global fp128 0xL00000000000000007FFF000000000000, align 16
@y = local_unnamed_addr global fp128 0xL00000000000000007FFF000000000000, align 16
@@ -38,6 +40,22 @@ define i32 @test_load_and_cmp() nounwind {
; RV32I-NEXT: lw ra, 44(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 48
; RV32I-NEXT: ret
+;
+; RV64I-LABEL: test_load_and_cmp:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lui a1, %hi(x)
+; RV64I-NEXT: lui a3, %hi(y)
+; RV64I-NEXT: ld a0, %lo(x)(a1)
+; RV64I-NEXT: ld a1, %lo(x+8)(a1)
+; RV64I-NEXT: ld a2, %lo(y)(a3)
+; RV64I-NEXT: ld a3, %lo(y+8)(a3)
+; RV64I-NEXT: call __netf2
+; RV64I-NEXT: snez a0, a0
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = load fp128, ptr @x, align 16
%2 = load fp128, ptr @y, align 16
%cmp = fcmp une fp128 %1, %2
@@ -85,6 +103,22 @@ define i32 @test_add_and_fptosi() nounwind {
; RV32I-NEXT: lw ra, 76(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 80
; RV32I-NEXT: ret
+;
+; RV64I-LABEL: test_add_and_fptosi:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lui a1, %hi(x)
+; RV64I-NEXT: lui a3, %hi(y)
+; RV64I-NEXT: ld a0, %lo(x)(a1)
+; RV64I-NEXT: ld a1, %lo(x+8)(a1)
+; RV64I-NEXT: ld a2, %lo(y)(a3)
+; RV64I-NEXT: ld a3, %lo(y+8)(a3)
+; RV64I-NEXT: call __addtf3
+; RV64I-NEXT: call __fixtfsi
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = load fp128, ptr @x, align 16
%2 = load fp128, ptr @y, align 16
%3 = fadd fp128 %1, %2
@@ -137,6 +171,19 @@ define fp128 @fmaximum(fp128 %x, fp128 %y) {
; RV32I-NEXT: addi sp, sp, 64
; RV32I-NEXT: .cfi_def_cfa_offset 0
; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fmaximum:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: .cfi_def_cfa_offset 16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: .cfi_offset ra, -8
+; RV64I-NEXT: call fmaximuml
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: .cfi_restore ra
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: .cfi_def_cfa_offset 0
+; RV64I-NEXT: ret
%a = call fp128 @llvm.maximum.fp128(fp128 %x, fp128 %y)
ret fp128 %a
}
@@ -186,6 +233,19 @@ define fp128 @fminimum(fp128 %x, fp128 %y) {
; RV32I-NEXT: addi sp, sp, 64
; RV32I-NEXT: .cfi_def_cfa_offset 0
; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fminimum:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: .cfi_def_cfa_offset 16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: .cfi_offset ra, -8
+; RV64I-NEXT: call fminimuml
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: .cfi_restore ra
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: .cfi_def_cfa_offset 0
+; RV64I-NEXT: ret
%a = call fp128 @llvm.minimum.fp128(fp128 %x, fp128 %y)
ret fp128 %a
}
@@ -229,6 +289,28 @@ define { fp128, fp128 } @modf(fp128 %a) nounwind {
; RV32I-NEXT: lw s0, 56(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 64
; RV32I-NEXT: ret
+;
+; RV64I-LABEL: modf:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -32
+; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
+; RV64I-NEXT: mv a3, a2
+; RV64I-NEXT: mv s0, a0
+; RV64I-NEXT: mv a2, sp
+; RV64I-NEXT: mv a0, a1
+; RV64I-NEXT: mv a1, a3
+; RV64I-NEXT: call modfl
+; RV64I-NEXT: ld a2, 0(sp)
+; RV64I-NEXT: ld a3, 8(sp)
+; RV64I-NEXT: sd a0, 0(s0)
+; RV64I-NEXT: sd a1, 8(s0)
+; RV64I-NEXT: sd a2, 16(s0)
+; RV64I-NEXT: sd a3, 24(s0)
+; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 32
+; RV64I-NEXT: ret
%result = call { fp128, fp128 } @llvm.modf.f128(fp128 %a)
ret { fp128, fp128 } %result
}
@@ -443,6 +525,15 @@ define i96 @fptosi_fp128_to_i96(fp128 %a) nounwind {
; RV32I-NEXT: lw s10, 64(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 112
; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fptosi_fp128_to_i96:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: call __fixtfti
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%result = fptosi fp128 %a to i96
ret i96 %result
}
>From 07b79d8f1d22b56a2de9de4ff21131495af33d01 Mon Sep 17 00:00:00 2001
From: Kane Wang <wangqiang1 at kylinos.cn>
Date: Mon, 3 Aug 2026 15:05:51 +0800
Subject: [PATCH 2/2] [RISCV] Pick correct lround libcall for fp128
LROUND with an i32 result on rv64 chose the libcall as f64 ? LROUND_F64
: LROUND_F32, so fp128 fell through to the f32 libcall (lroundf) and
lost precision. Use RTLIB::getLROUND, which maps fp128 to lroundl.
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 4 +--
llvm/test/CodeGen/RISCV/fp128.ll | 36 +++++++++++++++++++++
2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index e23427482c1e4..cd03dbed23ee7 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -15730,8 +15730,8 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
// If the FP type needs to be softened, emit a library call to lround. We'll
// need to truncate the result. We assume any value that doesn't fit in i32
// is allowed to return an unspecified value.
- RTLIB::Libcall LC =
- Op0.getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
+ RTLIB::Libcall LC = RTLIB::getLROUND(Op0.getValueType());
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected FP type for LROUND!");
MakeLibCallOptions CallOptions;
EVT OpVT = Op0.getValueType();
CallOptions.setTypeListBeforeSoften(OpVT, MVT::i64);
diff --git a/llvm/test/CodeGen/RISCV/fp128.ll b/llvm/test/CodeGen/RISCV/fp128.ll
index a5bcfae678a1a..9beecf0c025c8 100644
--- a/llvm/test/CodeGen/RISCV/fp128.ll
+++ b/llvm/test/CodeGen/RISCV/fp128.ll
@@ -537,3 +537,39 @@ define i96 @fptosi_fp128_to_i96(fp128 %a) nounwind {
%result = fptosi fp128 %a to i96
ret i96 %result
}
+
+define i32 @lround_f128() nounwind {
+; RV32I-LABEL: lround_f128:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -32
+; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
+; RV32I-NEXT: lui a0, %hi(x)
+; RV32I-NEXT: lw a1, %lo(x)(a0)
+; RV32I-NEXT: lw a2, %lo(x+4)(a0)
+; RV32I-NEXT: lw a3, %lo(x+8)(a0)
+; RV32I-NEXT: lw a4, %lo(x+12)(a0)
+; RV32I-NEXT: addi a0, sp, 8
+; RV32I-NEXT: sw a1, 8(sp)
+; RV32I-NEXT: sw a2, 12(sp)
+; RV32I-NEXT: sw a3, 16(sp)
+; RV32I-NEXT: sw a4, 20(sp)
+; RV32I-NEXT: call lroundl
+; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 32
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: lround_f128:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lui a1, %hi(x)
+; RV64I-NEXT: ld a0, %lo(x)(a1)
+; RV64I-NEXT: ld a1, %lo(x+8)(a1)
+; RV64I-NEXT: call lroundl
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = load fp128, ptr @x, align 16
+ %r = call i32 @llvm.lround.f128(fp128 %1)
+ ret i32 %r
+}
More information about the llvm-commits
mailing list