[llvm] [RISCV][GlobalISel] Fix fptosi/fptoui from half to i64 on RV32 (PR #222316)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 9 05:50:29 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Kane Wang (ReVe1uv)
<details>
<summary>Changes</summary>
The fcvt.l[u].h patterns are RV64-only, so RV32 had no rule for `G_FPTOSI/G_FPTOUI` with `{s64, s16}.` Fall back to the half-variant conversion libcalls `(__fixhfdi/__fixunshfdi)`, matching SelectionDAG.
---
Full diff: https://github.com/llvm/llvm-project/pull/222316.diff
2 Files Affected:
- (modified) llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp (+3)
- (added) llvm/test/CodeGen/RISCV/GlobalISel/half-convert.ll (+57)
``````````diff
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index d0ee9bb39cc8b..a8b60bfe9b926 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -631,6 +631,9 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
.widenScalarToNextPow2(0)
.minScalar(0, s32)
.libcallFor({{s32, s32}, {s64, s32}, {s32, s64}, {s64, s64}})
+ // The fcvt.l[u].h conversions are RV64-only, so RV32 falls back to the
+ // half-variant conversion libcalls.
+ .libcallFor({{s64, s16}})
.libcallFor(ST.is64Bit(), {{s32, s128}, {s64, s128}}) // FIXME RV32.
.libcallFor(ST.is64Bit(), {{s128, s32}, {s128, s64}, {s128, s128}});
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/half-convert.ll b/llvm/test/CodeGen/RISCV/GlobalISel/half-convert.ll
new file mode 100644
index 0000000000000..d7e18681e13c0
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/half-convert.ll
@@ -0,0 +1,57 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -global-isel -mattr=+f,+d,+zfh -target-abi=ilp32d < %s | FileCheck %s --check-prefixes=CHECK,RV32
+; RUN: llc -mtriple=riscv64 -global-isel -mattr=+f,+d,+zfh -target-abi=lp64d < %s | FileCheck %s --check-prefixes=CHECK,RV64
+
+define i64 @fptoui_i64_f16(half %x) nounwind {
+; RV32-LABEL: fptoui_i64_f16:
+; RV32: # %bb.0:
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: call __fixunshfdi
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: ret
+;
+; RV64-LABEL: fptoui_i64_f16:
+; RV64: # %bb.0:
+; RV64-NEXT: fcvt.lu.h a0, fa0, rtz
+; RV64-NEXT: ret
+ %a = fptoui half %x to i64
+ ret i64 %a
+}
+
+define i64 @fptosi_i64_f16(half %x) nounwind {
+; RV32-LABEL: fptosi_i64_f16:
+; RV32: # %bb.0:
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: call __fixhfdi
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: ret
+;
+; RV64-LABEL: fptosi_i64_f16:
+; RV64: # %bb.0:
+; RV64-NEXT: fcvt.l.h a0, fa0, rtz
+; RV64-NEXT: ret
+ %a = fptosi half %x to i64
+ ret i64 %a
+}
+
+define i32 @fptoui_i32_f16(half %x) nounwind {
+; CHECK-LABEL: fptoui_i32_f16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: fcvt.wu.h a0, fa0, rtz
+; CHECK-NEXT: ret
+ %a = fptoui half %x to i32
+ ret i32 %a
+}
+
+define i32 @fptosi_i32_f16(half %x) nounwind {
+; CHECK-LABEL: fptosi_i32_f16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: fcvt.w.h a0, fa0, rtz
+; CHECK-NEXT: ret
+ %a = fptosi half %x to i32
+ ret i32 %a
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/222316
More information about the llvm-commits
mailing list