Skip to content

Commit 30bdea1

Browse files
wszqkzqkhulxv
authored andcommitted
[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: lcpu-club/loongarch-packages#974. Both the LLVM side and the Highway test suite that discovered the bug have passed verification. Assisted by Kimi K3 AI agent. Fixes #214605
1 parent b88a76c commit 30bdea1

3 files changed

Lines changed: 12 additions & 10 deletions

File tree

llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2193,9 +2193,9 @@ def : Pat<(v8f32 (loongarch_vffint_s_l (v4i64 LASX256:$xj), (v4i64 LASX256:$xk))
21932193
// XVFTINTRZ_{W_S/L_D}
21942194
def : Pat<(v8i32 (fp_to_sint v8f32:$vj)), (XVFTINTRZ_W_S v8f32:$vj)>;
21952195
def : Pat<(v4i64 (fp_to_sint v4f64:$vj)), (XVFTINTRZ_L_D v4f64:$vj)>;
2196-
def : Pat<(v4i64(fp_to_sint v4f32:$vj)), (VEXT2XV_D_W(SUBREG_TO_REG
2197-
(VFTINTRZ_W_S v4f32:$vj),
2198-
sub_128))>;
2196+
def : Pat<(v4i64 (fp_to_sint v4f32:$vj)),
2197+
(XVFTINTRZL_L_S
2198+
(XVPERMI_D (SUBREG_TO_REG v4f32:$vj, sub_128), 216))>;
21992199
def : Pat<(v4i32(fp_to_sint v4f64:$vj)),
22002200
(EXTRACT_SUBREG(XVPICKEV_W(XVPERMI_D(XVFTINTRZ_L_D v4f64:$vj), 238),
22012201
(XVFTINTRZ_L_D v4f64:$vj)),
@@ -2204,9 +2204,10 @@ def : Pat<(v4i32(fp_to_sint v4f64:$vj)),
22042204
// XVFTINTRZ_{W_SU/L_DU}
22052205
def : Pat<(v8i32 (fp_to_uint v8f32:$vj)), (XVFTINTRZ_WU_S v8f32:$vj)>;
22062206
def : Pat<(v4i64 (fp_to_uint v4f64:$vj)), (XVFTINTRZ_LU_D v4f64:$vj)>;
2207-
def : Pat<(v4i64(fp_to_uint v4f32:$vj)), (VEXT2XV_DU_WU(SUBREG_TO_REG
2208-
(VFTINTRZ_WU_S v4f32:$vj),
2209-
sub_128))>;
2207+
def : Pat<(v4i64 (fp_to_uint v4f32:$vj)),
2208+
(XVFTINTRZ_LU_D
2209+
(XVFCVTL_D_S
2210+
(XVPERMI_D (SUBREG_TO_REG v4f32:$vj, sub_128), 216)))>;
22102211
def : Pat<(v4i32(fp_to_uint v4f64:$vj)),
22112212
(EXTRACT_SUBREG(XVPICKEV_W(XVPERMI_D(XVFTINTRZ_LU_D v4f64:$vj), 238),
22122213
(XVFTINTRZ_LU_D v4f64:$vj)),

llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ define void @fptosi_v4f32_v4i64(ptr %res, ptr %in){
6161
; CHECK-LABEL: fptosi_v4f32_v4i64:
6262
; CHECK: # %bb.0:
6363
; CHECK-NEXT: vld $vr0, $a1, 0
64-
; CHECK-NEXT: vftintrz.w.s $vr0, $vr0
65-
; CHECK-NEXT: vext2xv.d.w $xr0, $xr0
64+
; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
65+
; CHECK-NEXT: xvftintrzl.l.s $xr0, $xr0
6666
; CHECK-NEXT: xvst $xr0, $a0, 0
6767
; CHECK-NEXT: ret
6868
%v0 = load <4 x float>, ptr %in

llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ define void @fptoui_v4f32_v4i64(ptr %res, ptr %in){
6767
; CHECK-LABEL: fptoui_v4f32_v4i64:
6868
; CHECK: # %bb.0:
6969
; CHECK-NEXT: vld $vr0, $a1, 0
70-
; CHECK-NEXT: vftintrz.wu.s $vr0, $vr0
71-
; CHECK-NEXT: vext2xv.du.wu $xr0, $xr0
70+
; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
71+
; CHECK-NEXT: xvfcvtl.d.s $xr0, $xr0
72+
; CHECK-NEXT: xvftintrz.lu.d $xr0, $xr0
7273
; CHECK-NEXT: xvst $xr0, $a0, 0
7374
; CHECK-NEXT: ret
7475
%v0 = load <4 x float>, ptr %in

0 commit comments

Comments
 (0)