[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