[llvm-branch-commits] [llvm] release/23.x: [LoongArch][LASX] Fix fptosi/fptoui from <4 x float> to <4 x i64> (#214621) (PR #215165)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Aug 9 19:03:21 PDT 2026


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/215165

Backport 29d7baedd12ae93d93b2baaf9bdfe030ca36742f

Requested by: @wangleiat

>From d208ea23bfbeb74ed10802dbc10f08fa09906bd3 Mon Sep 17 00:00:00 2001
From: wszqkzqk <wszqkzqk at qq.com>
Date: Mon, 10 Aug 2026 09:53:54 +0800
Subject: [PATCH] [LoongArch][LASX] Fix fptosi/fptoui from <4 x float> to <4 x
 i64> (#214621)

These were lowered through a 128-bit f32 to i32/u32 conversion followed
by a sign/zero extension, which silently clamps any finite input that
does not fit in i32/u32 instead of producing the correct 64-bit integer.

Convert directly with xvftintrzl.l.s for the signed case. For the
unsigned case there is no f32 -> u64 lane conversion in LASX, so widen
to f64 first (which is exact) and convert with xvftintrz.lu.d. Both
forms use xvpermi.d to move the inputs into the low 64 bits of each
128-bit lane, as required by these lane-wise conversions.

Built and verified on Arch Linux for Loong64:
https://github.com/lcpu-club/loongarch-packages/pull/974. Both the LLVM
side and the Highway test suite that discovered the bug have passed
verification.
Assisted by Kimi K3 AI agent.

Fixes https://github.com/llvm/llvm-project/issues/214605

(cherry picked from commit 29d7baedd12ae93d93b2baaf9bdfe030ca36742f)
---
 llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td | 13 +++++++------
 .../CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll |  4 ++--
 .../CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll |  5 +++--
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index e75bfc690fe53..a1d1e96fca790 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -2165,9 +2165,9 @@ def : Pat<(v8f32 (loongarch_vffint_s_l (v4i64 LASX256:$xj), (v4i64 LASX256:$xk))
 // XVFTINTRZ_{W_S/L_D}
 def : Pat<(v8i32 (fp_to_sint v8f32:$vj)), (XVFTINTRZ_W_S v8f32:$vj)>;
 def : Pat<(v4i64 (fp_to_sint v4f64:$vj)), (XVFTINTRZ_L_D v4f64:$vj)>;
-def : Pat<(v4i64(fp_to_sint v4f32:$vj)), (VEXT2XV_D_W(SUBREG_TO_REG
-                                             (VFTINTRZ_W_S v4f32:$vj),
-                                             sub_128))>;
+def : Pat<(v4i64 (fp_to_sint v4f32:$vj)),
+          (XVFTINTRZL_L_S
+              (XVPERMI_D (SUBREG_TO_REG v4f32:$vj, sub_128), 216))>;
 def : Pat<(v4i32(fp_to_sint v4f64:$vj)),
           (EXTRACT_SUBREG(XVPICKEV_W(XVPERMI_D(XVFTINTRZ_L_D v4f64:$vj), 238),
                (XVFTINTRZ_L_D v4f64:$vj)),
@@ -2176,9 +2176,10 @@ def : Pat<(v4i32(fp_to_sint v4f64:$vj)),
 // XVFTINTRZ_{W_SU/L_DU}
 def : Pat<(v8i32 (fp_to_uint v8f32:$vj)), (XVFTINTRZ_WU_S v8f32:$vj)>;
 def : Pat<(v4i64 (fp_to_uint v4f64:$vj)), (XVFTINTRZ_LU_D v4f64:$vj)>;
-def : Pat<(v4i64(fp_to_uint v4f32:$vj)), (VEXT2XV_DU_WU(SUBREG_TO_REG
-                                             (VFTINTRZ_WU_S v4f32:$vj),
-                                             sub_128))>;
+def : Pat<(v4i64 (fp_to_uint v4f32:$vj)),
+          (XVFTINTRZ_LU_D
+              (XVFCVTL_D_S
+                  (XVPERMI_D (SUBREG_TO_REG v4f32:$vj, sub_128), 216)))>;
 def : Pat<(v4i32(fp_to_uint v4f64:$vj)),
           (EXTRACT_SUBREG(XVPICKEV_W(XVPERMI_D(XVFTINTRZ_LU_D v4f64:$vj), 238),
                (XVFTINTRZ_LU_D v4f64:$vj)),
diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll
index a7829eb7215d8..3ce79b79877b1 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll
@@ -61,8 +61,8 @@ define void @fptosi_v4f32_v4i64(ptr %res, ptr %in){
 ; CHECK-LABEL: fptosi_v4f32_v4i64:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    vld $vr0, $a1, 0
-; CHECK-NEXT:    vftintrz.w.s $vr0, $vr0
-; CHECK-NEXT:    vext2xv.d.w $xr0, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    xvftintrzl.l.s $xr0, $xr0
 ; CHECK-NEXT:    xvst $xr0, $a0, 0
 ; CHECK-NEXT:    ret
   %v0 = load <4 x float>, ptr %in
diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll
index 2ef774d93a619..53cdcbe927f6e 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll
@@ -67,8 +67,9 @@ define void @fptoui_v4f32_v4i64(ptr %res, ptr %in){
 ; CHECK-LABEL: fptoui_v4f32_v4i64:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    vld $vr0, $a1, 0
-; CHECK-NEXT:    vftintrz.wu.s $vr0, $vr0
-; CHECK-NEXT:    vext2xv.du.wu $xr0, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    xvfcvtl.d.s $xr0, $xr0
+; CHECK-NEXT:    xvftintrz.lu.d $xr0, $xr0
 ; CHECK-NEXT:    xvst $xr0, $a0, 0
 ; CHECK-NEXT:    ret
   %v0 = load <4 x float>, ptr %in



More information about the llvm-branch-commits mailing list