[llvm] [LoongArch] Combine FP_TO_UINT/FP_TO_SINT with [X]VFTINTRZ instruction (PR #201569)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 4 05:31:04 PDT 2026
https://github.com/lrzlin created https://github.com/llvm/llvm-project/pull/201569
Combine double convert to signed 32-bit integer with `[X]VFTINTRZ_W_D` instructions, avoid doing so with LASX double to uint32 because we already have the corresponding tablegen pattern.
Rely on: https://github.com/llvm/llvm-project/pull/201548
>From 815acdab0b61fa845dc01ae4794ae02d8e466c16 Mon Sep 17 00:00:00 2001
From: Lin Runze <linrunze at loongson.cn>
Date: Thu, 4 Jun 2026 19:59:22 +0800
Subject: [PATCH 1/2] [LoongArch][NFC] Add double to signed/unsigned i32 tests
for LSX and LASX
---
.../LoongArch/lasx/ir-instruction/fptosi.ll | 20 ++
.../LoongArch/lasx/ir-instruction/fptoui.ll | 123 +++++++++---
.../LoongArch/lsx/ir-instruction/fptosi.ll | 125 ++++++++++--
.../LoongArch/lsx/ir-instruction/fptoui.ll | 189 ++++++++++++++++--
4 files changed, 400 insertions(+), 57 deletions(-)
diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll
index 5b63ef3e53a4c..861052b0ffec1 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll
@@ -43,6 +43,26 @@ define void @fptosi_v4f64_v4i32(ptr %res, ptr %in){
ret void
}
+define void @fptosi_v8f64_v8i32(ptr %res, ptr %in){
+; CHECK-LABEL: fptosi_v8f64_v8i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a1, 32
+; CHECK-NEXT: xvld $xr1, $a1, 0
+; CHECK-NEXT: xvftintrz.l.d $xr0, $xr0
+; CHECK-NEXT: xvpermi.d $xr2, $xr0, 238
+; CHECK-NEXT: xvpickev.w $xr0, $xr2, $xr0
+; CHECK-NEXT: xvftintrz.l.d $xr1, $xr1
+; CHECK-NEXT: xvpermi.d $xr2, $xr1, 238
+; CHECK-NEXT: xvpickev.w $xr1, $xr2, $xr1
+; CHECK-NEXT: xvpermi.q $xr1, $xr0, 2
+; CHECK-NEXT: xvst $xr1, $a0, 0
+; CHECK-NEXT: ret
+ %v0 = load <8 x double>, ptr %in
+ %v1 = fptosi <8 x double> %v0 to <8 x i32>
+ store <8 x i32> %v1, ptr %res
+ ret void
+}
+
define void @fptosi_v4f32_v4i64(ptr %res, ptr %in){
; CHECK-LABEL: fptosi_v4f32_v4i64:
; CHECK: # %bb.0:
diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll
index 4c699a0721bff..0f60d782c0fc5 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll
@@ -1,14 +1,21 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
-; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lasx < %s | FileCheck %s
-; RUN: llc --mtriple=loongarch64 --mattr=+lasx < %s | FileCheck %s
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lasx < %s | FileCheck %s --check-prefix=LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx < %s | FileCheck %s --check-prefix=LA64
define void @fptoui_v8f32_v8i32(ptr %res, ptr %in){
-; CHECK-LABEL: fptoui_v8f32_v8i32:
-; CHECK: # %bb.0:
-; CHECK-NEXT: xvld $xr0, $a1, 0
-; CHECK-NEXT: xvftintrz.wu.s $xr0, $xr0
-; CHECK-NEXT: xvst $xr0, $a0, 0
-; CHECK-NEXT: ret
+; LA32-LABEL: fptoui_v8f32_v8i32:
+; LA32: # %bb.0:
+; LA32-NEXT: xvld $xr0, $a1, 0
+; LA32-NEXT: xvftintrz.wu.s $xr0, $xr0
+; LA32-NEXT: xvst $xr0, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptoui_v8f32_v8i32:
+; LA64: # %bb.0:
+; LA64-NEXT: xvld $xr0, $a1, 0
+; LA64-NEXT: xvftintrz.wu.s $xr0, $xr0
+; LA64-NEXT: xvst $xr0, $a0, 0
+; LA64-NEXT: ret
%v0 = load <8 x float>, ptr %in
%v1 = fptoui <8 x float> %v0 to <8 x i32>
store <8 x i32> %v1, ptr %res
@@ -16,12 +23,19 @@ define void @fptoui_v8f32_v8i32(ptr %res, ptr %in){
}
define void @fptoui_v4f64_v4i64(ptr %res, ptr %in){
-; CHECK-LABEL: fptoui_v4f64_v4i64:
-; CHECK: # %bb.0:
-; CHECK-NEXT: xvld $xr0, $a1, 0
-; CHECK-NEXT: xvftintrz.lu.d $xr0, $xr0
-; CHECK-NEXT: xvst $xr0, $a0, 0
-; CHECK-NEXT: ret
+; LA32-LABEL: fptoui_v4f64_v4i64:
+; LA32: # %bb.0:
+; LA32-NEXT: xvld $xr0, $a1, 0
+; LA32-NEXT: xvftintrz.lu.d $xr0, $xr0
+; LA32-NEXT: xvst $xr0, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptoui_v4f64_v4i64:
+; LA64: # %bb.0:
+; LA64-NEXT: xvld $xr0, $a1, 0
+; LA64-NEXT: xvftintrz.lu.d $xr0, $xr0
+; LA64-NEXT: xvst $xr0, $a0, 0
+; LA64-NEXT: ret
%v0 = load <4 x double>, ptr %in
%v1 = fptoui <4 x double> %v0 to <4 x i64>
store <4 x i64> %v1, ptr %res
@@ -29,28 +43,79 @@ define void @fptoui_v4f64_v4i64(ptr %res, ptr %in){
}
define void @fptoui_v4f64_v4i32(ptr %res, ptr %in){
-; CHECK-LABEL: fptoui_v4f64_v4i32:
-; CHECK: # %bb.0:
-; CHECK-NEXT: xvld $xr0, $a1, 0
-; CHECK-NEXT: xvftintrz.lu.d $xr0, $xr0
-; CHECK-NEXT: xvpermi.d $xr1, $xr0, 238
-; CHECK-NEXT: xvpickev.w $xr0, $xr1, $xr0
-; CHECK-NEXT: vst $vr0, $a0, 0
-; CHECK-NEXT: ret
+; LA32-LABEL: fptoui_v4f64_v4i32:
+; LA32: # %bb.0:
+; LA32-NEXT: xvld $xr0, $a1, 0
+; LA32-NEXT: xvftintrz.lu.d $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr1, $xr0, 238
+; LA32-NEXT: xvpickev.w $xr0, $xr1, $xr0
+; LA32-NEXT: vst $vr0, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptoui_v4f64_v4i32:
+; LA64: # %bb.0:
+; LA64-NEXT: xvld $xr0, $a1, 0
+; LA64-NEXT: xvftintrz.lu.d $xr0, $xr0
+; LA64-NEXT: xvpermi.d $xr1, $xr0, 238
+; LA64-NEXT: xvpickev.w $xr0, $xr1, $xr0
+; LA64-NEXT: vst $vr0, $a0, 0
+; LA64-NEXT: ret
%v0 = load <4 x double>, ptr %in
%v1 = fptoui <4 x double> %v0 to <4 x i32>
store <4 x i32> %v1, ptr %res
ret void
}
+define void @fptoui_v8f64_v8i32(ptr %res, ptr %in){
+; LA32-LABEL: fptoui_v8f64_v8i32:
+; LA32: # %bb.0:
+; LA32-NEXT: xvld $xr0, $a1, 32
+; LA32-NEXT: xvld $xr1, $a1, 0
+; LA32-NEXT: xvftintrz.lu.d $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr2, $xr0, 238
+; LA32-NEXT: xvpickev.w $xr0, $xr2, $xr0
+; LA32-NEXT: xvftintrz.lu.d $xr1, $xr1
+; LA32-NEXT: xvpermi.d $xr2, $xr1, 238
+; LA32-NEXT: xvpickev.w $xr1, $xr2, $xr1
+; LA32-NEXT: xvpermi.q $xr1, $xr0, 2
+; LA32-NEXT: xvst $xr1, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptoui_v8f64_v8i32:
+; LA64: # %bb.0:
+; LA64-NEXT: xvld $xr0, $a1, 32
+; LA64-NEXT: xvld $xr1, $a1, 0
+; LA64-NEXT: xvftintrz.lu.d $xr0, $xr0
+; LA64-NEXT: xvpermi.d $xr2, $xr0, 238
+; LA64-NEXT: xvpickev.w $xr0, $xr2, $xr0
+; LA64-NEXT: xvftintrz.lu.d $xr1, $xr1
+; LA64-NEXT: xvpermi.d $xr2, $xr1, 238
+; LA64-NEXT: xvpickev.w $xr1, $xr2, $xr1
+; LA64-NEXT: xvpermi.q $xr1, $xr0, 2
+; LA64-NEXT: xvst $xr1, $a0, 0
+; LA64-NEXT: ret
+ %v0 = load <8 x double>, ptr %in
+ %v1 = fptoui <8 x double> %v0 to <8 x i32>
+ store <8 x i32> %v1, ptr %res
+ ret void
+}
+
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: xvst $xr0, $a0, 0
-; CHECK-NEXT: ret
+; LA32-LABEL: fptoui_v4f32_v4i64:
+; LA32: # %bb.0:
+; LA32-NEXT: vld $vr0, $a1, 0
+; LA32-NEXT: vftintrz.wu.s $vr0, $vr0
+; LA32-NEXT: vext2xv.du.wu $xr0, $xr0
+; LA32-NEXT: xvst $xr0, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptoui_v4f32_v4i64:
+; LA64: # %bb.0:
+; LA64-NEXT: vld $vr0, $a1, 0
+; LA64-NEXT: vftintrz.wu.s $vr0, $vr0
+; LA64-NEXT: vext2xv.du.wu $xr0, $xr0
+; LA64-NEXT: xvst $xr0, $a0, 0
+; LA64-NEXT: ret
%v0 = load <4 x float>, ptr %in
%v1 = fptoui <4 x float> %v0 to <4 x i64>
store <4 x i64> %v1, ptr %res
diff --git a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll
index 7ea6d7431670e..76bc8225a4ae8 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll
@@ -1,14 +1,21 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
-; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lsx < %s | FileCheck %s
-; RUN: llc --mtriple=loongarch64 --mattr=+lsx < %s | FileCheck %s
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lsx < %s | FileCheck %s --check-prefix=LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx < %s | FileCheck %s --check-prefix=LA64
define void @fptosi_v4f32_v4i32(ptr %res, ptr %in){
-; CHECK-LABEL: fptosi_v4f32_v4i32:
-; CHECK: # %bb.0:
-; CHECK-NEXT: vld $vr0, $a1, 0
-; CHECK-NEXT: vftintrz.w.s $vr0, $vr0
-; CHECK-NEXT: vst $vr0, $a0, 0
-; CHECK-NEXT: ret
+; LA32-LABEL: fptosi_v4f32_v4i32:
+; LA32: # %bb.0:
+; LA32-NEXT: vld $vr0, $a1, 0
+; LA32-NEXT: vftintrz.w.s $vr0, $vr0
+; LA32-NEXT: vst $vr0, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptosi_v4f32_v4i32:
+; LA64: # %bb.0:
+; LA64-NEXT: vld $vr0, $a1, 0
+; LA64-NEXT: vftintrz.w.s $vr0, $vr0
+; LA64-NEXT: vst $vr0, $a0, 0
+; LA64-NEXT: ret
%v0 = load <4 x float>, ptr %in
%v1 = fptosi <4 x float> %v0 to <4 x i32>
store <4 x i32> %v1, ptr %res
@@ -16,14 +23,104 @@ define void @fptosi_v4f32_v4i32(ptr %res, ptr %in){
}
define void @fptosi_v2f64_v2i64(ptr %res, ptr %in){
-; CHECK-LABEL: fptosi_v2f64_v2i64:
-; CHECK: # %bb.0:
-; CHECK-NEXT: vld $vr0, $a1, 0
-; CHECK-NEXT: vftintrz.l.d $vr0, $vr0
-; CHECK-NEXT: vst $vr0, $a0, 0
-; CHECK-NEXT: ret
+; LA32-LABEL: fptosi_v2f64_v2i64:
+; LA32: # %bb.0:
+; LA32-NEXT: vld $vr0, $a1, 0
+; LA32-NEXT: vftintrz.l.d $vr0, $vr0
+; LA32-NEXT: vst $vr0, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptosi_v2f64_v2i64:
+; LA64: # %bb.0:
+; LA64-NEXT: vld $vr0, $a1, 0
+; LA64-NEXT: vftintrz.l.d $vr0, $vr0
+; LA64-NEXT: vst $vr0, $a0, 0
+; LA64-NEXT: ret
%v0 = load <2 x double>, ptr %in
%v1 = fptosi <2 x double> %v0 to <2 x i64>
store <2 x i64> %v1, ptr %res
ret void
}
+
+define void @fptosi_v2f64_v2i32(ptr %res, ptr %in){
+; LA32-LABEL: fptosi_v2f64_v2i32:
+; LA32: # %bb.0:
+; LA32-NEXT: vld $vr0, $a1, 0
+; LA32-NEXT: vreplvei.d $vr1, $vr0, 0
+; LA32-NEXT: ftintrz.w.d $fa1, $fa1
+; LA32-NEXT: vreplvei.d $vr0, $vr0, 1
+; LA32-NEXT: ftintrz.w.d $fa0, $fa0
+; LA32-NEXT: fst.s $fa0, $a0, 4
+; LA32-NEXT: fst.s $fa1, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptosi_v2f64_v2i32:
+; LA64: # %bb.0:
+; LA64-NEXT: vld $vr0, $a1, 0
+; LA64-NEXT: vreplvei.d $vr1, $vr0, 0
+; LA64-NEXT: ftintrz.w.d $fa1, $fa1
+; LA64-NEXT: movfr2gr.s $a1, $fa1
+; LA64-NEXT: vinsgr2vr.w $vr1, $a1, 0
+; LA64-NEXT: vreplvei.d $vr0, $vr0, 1
+; LA64-NEXT: ftintrz.w.d $fa0, $fa0
+; LA64-NEXT: movfr2gr.s $a1, $fa0
+; LA64-NEXT: vinsgr2vr.w $vr1, $a1, 1
+; LA64-NEXT: vstelm.d $vr1, $a0, 0, 0
+; LA64-NEXT: ret
+ %v0 = load <2 x double>, ptr %in
+ %v1 = fptosi <2 x double> %v0 to <2 x i32>
+ store <2 x i32> %v1, ptr %res
+ ret void
+}
+
+define void @fptosi_v4f64_v4i32(ptr %res, ptr %in){
+; LA32-LABEL: fptosi_v4f64_v4i32:
+; LA32: # %bb.0:
+; LA32-NEXT: vld $vr0, $a1, 0
+; LA32-NEXT: vld $vr1, $a1, 16
+; LA32-NEXT: vreplvei.d $vr2, $vr0, 0
+; LA32-NEXT: ftintrz.w.d $fa2, $fa2
+; LA32-NEXT: movfr2gr.s $a1, $fa2
+; LA32-NEXT: vinsgr2vr.w $vr2, $a1, 0
+; LA32-NEXT: vreplvei.d $vr0, $vr0, 1
+; LA32-NEXT: ftintrz.w.d $fa0, $fa0
+; LA32-NEXT: movfr2gr.s $a1, $fa0
+; LA32-NEXT: vinsgr2vr.w $vr2, $a1, 1
+; LA32-NEXT: vreplvei.d $vr0, $vr1, 0
+; LA32-NEXT: ftintrz.w.d $fa0, $fa0
+; LA32-NEXT: movfr2gr.s $a1, $fa0
+; LA32-NEXT: vinsgr2vr.w $vr2, $a1, 2
+; LA32-NEXT: vreplvei.d $vr0, $vr1, 1
+; LA32-NEXT: ftintrz.w.d $fa0, $fa0
+; LA32-NEXT: movfr2gr.s $a1, $fa0
+; LA32-NEXT: vinsgr2vr.w $vr2, $a1, 3
+; LA32-NEXT: vst $vr2, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptosi_v4f64_v4i32:
+; LA64: # %bb.0:
+; LA64-NEXT: vld $vr0, $a1, 0
+; LA64-NEXT: vld $vr1, $a1, 16
+; LA64-NEXT: vreplvei.d $vr2, $vr0, 0
+; LA64-NEXT: ftintrz.w.d $fa2, $fa2
+; LA64-NEXT: movfr2gr.s $a1, $fa2
+; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 0
+; LA64-NEXT: vreplvei.d $vr0, $vr0, 1
+; LA64-NEXT: ftintrz.w.d $fa0, $fa0
+; LA64-NEXT: movfr2gr.s $a1, $fa0
+; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 1
+; LA64-NEXT: vreplvei.d $vr0, $vr1, 0
+; LA64-NEXT: ftintrz.w.d $fa0, $fa0
+; LA64-NEXT: movfr2gr.s $a1, $fa0
+; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 2
+; LA64-NEXT: vreplvei.d $vr0, $vr1, 1
+; LA64-NEXT: ftintrz.w.d $fa0, $fa0
+; LA64-NEXT: movfr2gr.s $a1, $fa0
+; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 3
+; LA64-NEXT: vst $vr2, $a0, 0
+; LA64-NEXT: ret
+ %v0 = load <4 x double>, ptr %in
+ %v1 = fptosi <4 x double> %v0 to <4 x i32>
+ store <4 x i32> %v1, ptr %res
+ ret void
+}
diff --git a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll
index ec3a86713ed23..c2ead7f2dfe33 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll
@@ -1,14 +1,21 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
-; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lsx < %s | FileCheck %s
-; RUN: llc --mtriple=loongarch64 --mattr=+lsx < %s | FileCheck %s
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lsx < %s | FileCheck %s --check-prefix=LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx < %s | FileCheck %s --check-prefix=LA64
define void @fptoui_v4f32_v4i32(ptr %res, ptr %in){
-; CHECK-LABEL: fptoui_v4f32_v4i32:
-; CHECK: # %bb.0:
-; CHECK-NEXT: vld $vr0, $a1, 0
-; CHECK-NEXT: vftintrz.wu.s $vr0, $vr0
-; CHECK-NEXT: vst $vr0, $a0, 0
-; CHECK-NEXT: ret
+; LA32-LABEL: fptoui_v4f32_v4i32:
+; LA32: # %bb.0:
+; LA32-NEXT: vld $vr0, $a1, 0
+; LA32-NEXT: vftintrz.wu.s $vr0, $vr0
+; LA32-NEXT: vst $vr0, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptoui_v4f32_v4i32:
+; LA64: # %bb.0:
+; LA64-NEXT: vld $vr0, $a1, 0
+; LA64-NEXT: vftintrz.wu.s $vr0, $vr0
+; LA64-NEXT: vst $vr0, $a0, 0
+; LA64-NEXT: ret
%v0 = load <4 x float>, ptr %in
%v1 = fptoui <4 x float> %v0 to <4 x i32>
store <4 x i32> %v1, ptr %res
@@ -16,14 +23,168 @@ define void @fptoui_v4f32_v4i32(ptr %res, ptr %in){
}
define void @fptoui_v2f64_v2i64(ptr %res, ptr %in){
-; CHECK-LABEL: fptoui_v2f64_v2i64:
-; CHECK: # %bb.0:
-; CHECK-NEXT: vld $vr0, $a1, 0
-; CHECK-NEXT: vftintrz.lu.d $vr0, $vr0
-; CHECK-NEXT: vst $vr0, $a0, 0
-; CHECK-NEXT: ret
+; LA32-LABEL: fptoui_v2f64_v2i64:
+; LA32: # %bb.0:
+; LA32-NEXT: vld $vr0, $a1, 0
+; LA32-NEXT: vftintrz.lu.d $vr0, $vr0
+; LA32-NEXT: vst $vr0, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptoui_v2f64_v2i64:
+; LA64: # %bb.0:
+; LA64-NEXT: vld $vr0, $a1, 0
+; LA64-NEXT: vftintrz.lu.d $vr0, $vr0
+; LA64-NEXT: vst $vr0, $a0, 0
+; LA64-NEXT: ret
%v0 = load <2 x double>, ptr %in
%v1 = fptoui <2 x double> %v0 to <2 x i64>
store <2 x i64> %v1, ptr %res
ret void
}
+
+define void @fptoui_v2f64_v2i32(ptr %res, ptr %in){
+; LA32-LABEL: fptoui_v2f64_v2i32:
+; LA32: # %bb.0:
+; LA32-NEXT: vld $vr0, $a1, 0
+; LA32-NEXT: vreplvei.d $vr1, $vr0, 0
+; LA32-NEXT: movgr2fr.w $fa2, $zero
+; LA32-NEXT: lu12i.w $a1, 269824
+; LA32-NEXT: movgr2frh.w $fa2, $a1
+; LA32-NEXT: fcmp.clt.d $fcc0, $fa1, $fa2
+; LA32-NEXT: fsub.d $fa3, $fa1, $fa2
+; LA32-NEXT: ftintrz.w.d $fa3, $fa3
+; LA32-NEXT: movfr2gr.s $a1, $fa3
+; LA32-NEXT: lu12i.w $a2, -524288
+; LA32-NEXT: xor $a1, $a1, $a2
+; LA32-NEXT: movcf2gr $a3, $fcc0
+; LA32-NEXT: masknez $a1, $a1, $a3
+; LA32-NEXT: ftintrz.w.d $fa1, $fa1
+; LA32-NEXT: movfr2gr.s $a4, $fa1
+; LA32-NEXT: maskeqz $a3, $a4, $a3
+; LA32-NEXT: or $a1, $a3, $a1
+; LA32-NEXT: vreplvei.d $vr0, $vr0, 1
+; LA32-NEXT: fcmp.clt.d $fcc0, $fa0, $fa2
+; LA32-NEXT: fsub.d $fa1, $fa0, $fa2
+; LA32-NEXT: ftintrz.w.d $fa1, $fa1
+; LA32-NEXT: movfr2gr.s $a3, $fa1
+; LA32-NEXT: xor $a2, $a3, $a2
+; LA32-NEXT: movcf2gr $a3, $fcc0
+; LA32-NEXT: masknez $a2, $a2, $a3
+; LA32-NEXT: ftintrz.w.d $fa0, $fa0
+; LA32-NEXT: movfr2gr.s $a4, $fa0
+; LA32-NEXT: maskeqz $a3, $a4, $a3
+; LA32-NEXT: or $a2, $a3, $a2
+; LA32-NEXT: st.w $a2, $a0, 4
+; LA32-NEXT: st.w $a1, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptoui_v2f64_v2i32:
+; LA64: # %bb.0:
+; LA64-NEXT: vld $vr0, $a1, 0
+; LA64-NEXT: vreplvei.d $vr1, $vr0, 0
+; LA64-NEXT: ftintrz.l.d $fa1, $fa1
+; LA64-NEXT: movfr2gr.d $a1, $fa1
+; LA64-NEXT: vinsgr2vr.w $vr1, $a1, 0
+; LA64-NEXT: vreplvei.d $vr0, $vr0, 1
+; LA64-NEXT: ftintrz.l.d $fa0, $fa0
+; LA64-NEXT: movfr2gr.d $a1, $fa0
+; LA64-NEXT: vinsgr2vr.w $vr1, $a1, 1
+; LA64-NEXT: vstelm.d $vr1, $a0, 0, 0
+; LA64-NEXT: ret
+ %v0 = load <2 x double>, ptr %in
+ %v1 = fptoui <2 x double> %v0 to <2 x i32>
+ store <2 x i32> %v1, ptr %res
+ ret void
+}
+
+define void @fptoui_v4f64_v4i32(ptr %res, ptr %in){
+; LA32-LABEL: fptoui_v4f64_v4i32:
+; LA32: # %bb.0:
+; LA32-NEXT: vld $vr0, $a1, 0
+; LA32-NEXT: vld $vr1, $a1, 16
+; LA32-NEXT: vreplvei.d $vr2, $vr0, 1
+; LA32-NEXT: movgr2fr.w $fa3, $zero
+; LA32-NEXT: lu12i.w $a1, 269824
+; LA32-NEXT: movgr2frh.w $fa3, $a1
+; LA32-NEXT: fcmp.clt.d $fcc0, $fa2, $fa3
+; LA32-NEXT: fsub.d $fa4, $fa2, $fa3
+; LA32-NEXT: ftintrz.w.d $fa4, $fa4
+; LA32-NEXT: movfr2gr.s $a1, $fa4
+; LA32-NEXT: lu12i.w $a2, -524288
+; LA32-NEXT: xor $a1, $a1, $a2
+; LA32-NEXT: movcf2gr $a3, $fcc0
+; LA32-NEXT: masknez $a1, $a1, $a3
+; LA32-NEXT: ftintrz.w.d $fa2, $fa2
+; LA32-NEXT: movfr2gr.s $a4, $fa2
+; LA32-NEXT: maskeqz $a3, $a4, $a3
+; LA32-NEXT: or $a1, $a3, $a1
+; LA32-NEXT: vreplvei.d $vr0, $vr0, 0
+; LA32-NEXT: fcmp.clt.d $fcc0, $fa0, $fa3
+; LA32-NEXT: fsub.d $fa2, $fa0, $fa3
+; LA32-NEXT: ftintrz.w.d $fa2, $fa2
+; LA32-NEXT: movfr2gr.s $a3, $fa2
+; LA32-NEXT: xor $a3, $a3, $a2
+; LA32-NEXT: movcf2gr $a4, $fcc0
+; LA32-NEXT: masknez $a3, $a3, $a4
+; LA32-NEXT: ftintrz.w.d $fa0, $fa0
+; LA32-NEXT: movfr2gr.s $a5, $fa0
+; LA32-NEXT: maskeqz $a4, $a5, $a4
+; LA32-NEXT: or $a3, $a4, $a3
+; LA32-NEXT: vinsgr2vr.w $vr0, $a3, 0
+; LA32-NEXT: vinsgr2vr.w $vr0, $a1, 1
+; LA32-NEXT: vreplvei.d $vr2, $vr1, 0
+; LA32-NEXT: fcmp.clt.d $fcc0, $fa2, $fa3
+; LA32-NEXT: fsub.d $fa4, $fa2, $fa3
+; LA32-NEXT: ftintrz.w.d $fa4, $fa4
+; LA32-NEXT: movfr2gr.s $a1, $fa4
+; LA32-NEXT: xor $a1, $a1, $a2
+; LA32-NEXT: movcf2gr $a3, $fcc0
+; LA32-NEXT: masknez $a1, $a1, $a3
+; LA32-NEXT: ftintrz.w.d $fa2, $fa2
+; LA32-NEXT: movfr2gr.s $a4, $fa2
+; LA32-NEXT: maskeqz $a3, $a4, $a3
+; LA32-NEXT: or $a1, $a3, $a1
+; LA32-NEXT: vinsgr2vr.w $vr0, $a1, 2
+; LA32-NEXT: vreplvei.d $vr1, $vr1, 1
+; LA32-NEXT: fcmp.clt.d $fcc0, $fa1, $fa3
+; LA32-NEXT: fsub.d $fa2, $fa1, $fa3
+; LA32-NEXT: ftintrz.w.d $fa2, $fa2
+; LA32-NEXT: movfr2gr.s $a1, $fa2
+; LA32-NEXT: xor $a1, $a1, $a2
+; LA32-NEXT: movcf2gr $a2, $fcc0
+; LA32-NEXT: masknez $a1, $a1, $a2
+; LA32-NEXT: ftintrz.w.d $fa1, $fa1
+; LA32-NEXT: movfr2gr.s $a3, $fa1
+; LA32-NEXT: maskeqz $a2, $a3, $a2
+; LA32-NEXT: or $a1, $a2, $a1
+; LA32-NEXT: vinsgr2vr.w $vr0, $a1, 3
+; LA32-NEXT: vst $vr0, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: fptoui_v4f64_v4i32:
+; LA64: # %bb.0:
+; LA64-NEXT: vld $vr0, $a1, 0
+; LA64-NEXT: vld $vr1, $a1, 16
+; LA64-NEXT: vreplvei.d $vr2, $vr0, 0
+; LA64-NEXT: ftintrz.l.d $fa2, $fa2
+; LA64-NEXT: movfr2gr.d $a1, $fa2
+; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 0
+; LA64-NEXT: vreplvei.d $vr0, $vr0, 1
+; LA64-NEXT: ftintrz.l.d $fa0, $fa0
+; LA64-NEXT: movfr2gr.d $a1, $fa0
+; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 1
+; LA64-NEXT: vreplvei.d $vr0, $vr1, 0
+; LA64-NEXT: ftintrz.l.d $fa0, $fa0
+; LA64-NEXT: movfr2gr.d $a1, $fa0
+; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 2
+; LA64-NEXT: vreplvei.d $vr0, $vr1, 1
+; LA64-NEXT: ftintrz.l.d $fa0, $fa0
+; LA64-NEXT: movfr2gr.d $a1, $fa0
+; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 3
+; LA64-NEXT: vst $vr2, $a0, 0
+; LA64-NEXT: ret
+ %v0 = load <4 x double>, ptr %in
+ %v1 = fptoui <4 x double> %v0 to <4 x i32>
+ store <4 x i32> %v1, ptr %res
+ ret void
+}
>From c99ccb0a42e98c6934580c02592e4c8b438c0e8a Mon Sep 17 00:00:00 2001
From: Lin Runze <linrunze at loongson.cn>
Date: Thu, 4 Jun 2026 10:31:58 +0800
Subject: [PATCH 2/2] [LoongArch] Combine FP_TO_UINT/FP_TO_SINT with
[X]VFTINTRZ instruction
---
.../LoongArch/LoongArchISelLowering.cpp | 102 ++++++++++++++
.../LoongArch/LoongArchLASXInstrInfo.td | 4 +
.../Target/LoongArch/LoongArchLSXInstrInfo.td | 9 ++
.../LoongArch/lasx/ir-instruction/fptosi.ll | 20 +--
.../LoongArch/lsx/ir-instruction/fptosi.ll | 60 ++-------
.../LoongArch/lsx/ir-instruction/fptoui.ll | 125 ++----------------
6 files changed, 147 insertions(+), 173 deletions(-)
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 561064b3e1090..5b2f1b34cf50b 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -512,6 +512,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);
setTargetDAGCombine(ISD::BITCAST);
setTargetDAGCombine(ISD::VSELECT);
+ setTargetDAGCombine(ISD::FP_TO_SINT);
+ setTargetDAGCombine(ISD::FP_TO_UINT);
}
// Set DAG combine for 'LASX' feature.
@@ -7784,6 +7786,103 @@ static SDValue performSINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+// Using [X]VFTINTRZ_W_D for double to signed 32-bit integer conversion.
+// For example:
+// v4i32 = fp_to_sint (concat_vectors v2f64, v2f64)
+// Can be combined into:
+// v4i32 = VFTINTRZ_W_D v2f64. v2f64
+static SDValue performFP_TO_INTCombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const LoongArchSubtarget &Subtarget) {
+ if (!Subtarget.hasExtLSX())
+ return SDValue();
+
+ SDLoc DL(N);
+ EVT DstVT = N->getValueType(0);
+ SDValue Src = N->getOperand(0);
+ EVT SrcVT = Src.getValueType();
+ bool IsSigned = N->getOpcode() == ISD::FP_TO_SINT;
+
+ if (!DstVT.isVector() || !DstVT.isSimple() || !SrcVT.isSimple())
+ return SDValue();
+
+ unsigned SrcEltBits = SrcVT.getScalarSizeInBits();
+ unsigned SrcBits = SrcVT.getSizeInBits();
+ unsigned DstEltBits = DstVT.getScalarSizeInBits();
+ unsigned NumElts = DstVT.getVectorNumElements();
+ unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
+
+ if (!isPowerOf2_32(NumElts) || !isPowerOf2_32(DstEltBits))
+ return SDValue();
+
+ if (SrcBits % BlockBits != 0 && SrcBits != 128)
+ return SDValue();
+
+ if (DstEltBits < 32) {
+ MVT PromoteVT = MVT::getVectorVT(MVT::getIntegerVT(32), NumElts);
+ SDValue Conv = DAG.getNode(N->getOpcode(), DL, PromoteVT, Src);
+ return DAG.getNode(ISD::TRUNCATE, DL, DstVT, Conv);
+ }
+
+ if (SrcEltBits != 64 || DstEltBits != 32)
+ return SDValue();
+
+ if (!IsSigned) {
+ MVT TmpVT = MVT::getVectorVT(MVT::i64, NumElts);
+ SDValue Tmp = DAG.getNode(ISD::FP_TO_SINT, DL, TmpVT, Src);
+ return DAG.getNode(ISD::TRUNCATE, DL, DstVT, Tmp);
+ }
+
+ SmallVector<SDValue, 8> Blocks;
+ unsigned MidNumElts = BlockBits / SrcEltBits;
+ MVT MidVT = MVT::getVectorVT(MVT::getFloatingPointVT(SrcEltBits), MidNumElts);
+ if (Src.getOpcode() == ISD::CONCAT_VECTORS &&
+ Src.getOperand(0).getValueSizeInBits() == BlockBits) {
+ // Already split into per-register pieces by an earlier combine.
+ for (unsigned i = 0; i < Src.getNumOperands(); i++)
+ Blocks.push_back(Src.getOperand(i));
+ } else if (SrcBits > BlockBits) {
+ // Wider than one register: extract each BlockBits-wide sub-vector.
+ for (unsigned i = 0; i < SrcBits / BlockBits; i++)
+ Blocks.push_back(
+ DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, MidVT, Src,
+ DAG.getVectorIdxConstant(i * MidNumElts, DL)));
+ } else if (SrcBits < BlockBits) {
+ // Narrower than one register: widen into a BlockBits register.
+ Blocks.push_back(DAG.getNode(ISD::INSERT_SUBVECTOR, DL, MidVT,
+ DAG.getUNDEF(MidVT), Src,
+ DAG.getVectorIdxConstant(0, DL)));
+ } else {
+ Blocks.push_back(Src);
+ }
+
+ MVT NativeVT = BlockBits == 256 ? MVT::v8i32 : MVT::v4i32;
+ bool IsValidUpperBits = SrcBits >= BlockBits;
+ bool SelfPair = Blocks.size() <= 1;
+
+ SmallVector<SDValue, 4> Parts;
+ for (unsigned i = 0; i < Blocks.size(); i += 2) {
+ SDValue Lo = Blocks[i];
+ SDValue Hi = SelfPair ? Lo : Blocks[i + 1];
+ SDValue Res = DAG.getNode(LoongArchISD::VFTINTRZ, DL, NativeVT, Hi, Lo);
+
+ if (BlockBits == 256 && IsValidUpperBits) {
+ Res = DAG.getBitcast(MVT::v4i64, Res);
+ Res = DAG.getNode(
+ LoongArchISD::XVPERMI, DL, MVT::v4i64, Res,
+ DAG.getConstant(0b11011000, DL, Subtarget.getGRLenVT()));
+ Res = DAG.getBitcast(NativeVT, Res);
+ }
+
+ Parts.push_back(Res);
+ }
+
+ if (SelfPair)
+ return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, DstVT, Parts[0],
+ DAG.getVectorIdxConstant(0, DL));
+ return DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, Parts);
+}
+
// Try to widen AND, OR and XOR nodes to VT in order to remove casts around
// logical operations, like in the example below.
// or (and (truncate x, truncate y)),
@@ -8069,6 +8168,9 @@ SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N,
return performEXTENDCombine(N, DAG, DCI, Subtarget);
case ISD::SINT_TO_FP:
return performSINT_TO_FPCombine(N, DAG, DCI, Subtarget);
+ case ISD::FP_TO_SINT:
+ case ISD::FP_TO_UINT:
+ return performFP_TO_INTCombine(N, DAG, DCI, Subtarget);
case LoongArchISD::BITREV_W:
return performBITREV_WCombine(N, DAG, DCI, Subtarget);
case LoongArchISD::BR_CC:
diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index 0fb2b1d332f60..bea8da2188cc8 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -2120,6 +2120,10 @@ def : Pat<(v4i32(fp_to_uint v4f64:$vj)),
(XVFTINTRZ_LU_D v4f64:$vj)),
sub_128)>;
+// XVFTINTRZ_W_D
+def : Pat<(v8i32 (loongarch_vftintrz_w_d (v4f64 LASX256:$xj), (v4f64 LASX256:$xk))),
+ (XVFTINTRZ_W_D LASX256:$xj, LASX256:$xk)>;
+
// XVAVG_{B/H/W/D/BU/HU/WU/DU}, XVAVGR_{B/H/W/D/BU/HU/WU/DU}
defm : PatXrXr<avgfloors, "XVAVG">;
defm : PatXrXr<avgceils, "XVAVGR">;
diff --git a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
index 34d4e2435b39d..6b10e52b4c655 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
@@ -36,6 +36,8 @@ def SDT_LoongArchVFCVT_S_D : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisFP<0>,
SDTCisVec<1>, SDTCisFP<1>, SDTCisSameAs<1, 2>]>;
def SDT_LoongArchVFCVTLH_D_S : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisFP<0>,
SDTCisVec<1>, SDTCisFP<1>]>;
+def SDT_LoongArchVFTINTRZ_W_D : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<0>,
+ SDTCisVec<1>, SDTCisFP<1>, SDTCisSameAs<1, 2>]>;
// Target nodes.
@@ -107,6 +109,9 @@ def loongarch_vfcvth_d_s: SDNode<"LoongArchISD::VFCVTH", SDT_LoongArchVFCVTLH_D_
def loongarch_vsrlr: SDNode<"LoongArchISD::VSRLR", SDT_LoongArchV2R>;
def loongarch_vsrar: SDNode<"LoongArchISD::VSRAR", SDT_LoongArchV2R>;
+// Vector double-precision convert to 32-bit integer
+def loongarch_vftintrz_w_d: SDNode<"LoongArchISD::VFTINTRZ", SDT_LoongArchVFTINTRZ_W_D>;
+
def immZExt1 : ImmLeaf<GRLenVT, [{return isUInt<1>(Imm);}]>;
def immZExt2 : ImmLeaf<GRLenVT, [{return isUInt<2>(Imm);}]>;
def immZExt3 : ImmLeaf<GRLenVT, [{return isUInt<3>(Imm);}]>;
@@ -2300,6 +2305,10 @@ def : Pat<(v2i64 (fp_to_sint v2f64:$vj)), (VFTINTRZ_L_D v2f64:$vj)>;
def : Pat<(v4i32 (fp_to_uint v4f32:$vj)), (VFTINTRZ_WU_S v4f32:$vj)>;
def : Pat<(v2i64 (fp_to_uint v2f64:$vj)), (VFTINTRZ_LU_D v2f64:$vj)>;
+// VFTINTRZ_W_D
+def : Pat<(v4i32 (loongarch_vftintrz_w_d (v2f64 LSX128:$vj), (v2f64 LSX128:$vk))),
+ (VFTINTRZ_W_D LSX128:$vj, LSX128:$vk)>;
+
// Vector loads floating-point constants
def : Pat<(f32 f32imm_vldi:$in),
(f32 (EXTRACT_SUBREG (VLDI (to_f32imm_vldi f32imm_vldi:$in)), sub_32))>;
diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll
index 861052b0ffec1..17a4c23dd3e1d 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll
@@ -32,9 +32,8 @@ define void @fptosi_v4f64_v4i32(ptr %res, ptr %in){
; CHECK-LABEL: fptosi_v4f64_v4i32:
; CHECK: # %bb.0:
; CHECK-NEXT: xvld $xr0, $a1, 0
-; CHECK-NEXT: xvftintrz.l.d $xr0, $xr0
-; CHECK-NEXT: xvpermi.d $xr1, $xr0, 238
-; CHECK-NEXT: xvpickev.w $xr0, $xr1, $xr0
+; CHECK-NEXT: xvftintrz.w.d $xr0, $xr0, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
; CHECK-NEXT: vst $vr0, $a0, 0
; CHECK-NEXT: ret
%v0 = load <4 x double>, ptr %in
@@ -46,16 +45,11 @@ define void @fptosi_v4f64_v4i32(ptr %res, ptr %in){
define void @fptosi_v8f64_v8i32(ptr %res, ptr %in){
; CHECK-LABEL: fptosi_v8f64_v8i32:
; CHECK: # %bb.0:
-; CHECK-NEXT: xvld $xr0, $a1, 32
-; CHECK-NEXT: xvld $xr1, $a1, 0
-; CHECK-NEXT: xvftintrz.l.d $xr0, $xr0
-; CHECK-NEXT: xvpermi.d $xr2, $xr0, 238
-; CHECK-NEXT: xvpickev.w $xr0, $xr2, $xr0
-; CHECK-NEXT: xvftintrz.l.d $xr1, $xr1
-; CHECK-NEXT: xvpermi.d $xr2, $xr1, 238
-; CHECK-NEXT: xvpickev.w $xr1, $xr2, $xr1
-; CHECK-NEXT: xvpermi.q $xr1, $xr0, 2
-; CHECK-NEXT: xvst $xr1, $a0, 0
+; CHECK-NEXT: xvld $xr0, $a1, 0
+; CHECK-NEXT: xvld $xr1, $a1, 32
+; CHECK-NEXT: xvftintrz.w.d $xr0, $xr1, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: xvst $xr0, $a0, 0
; CHECK-NEXT: ret
%v0 = load <8 x double>, ptr %in
%v1 = fptosi <8 x double> %v0 to <8 x i32>
diff --git a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll
index 76bc8225a4ae8..4989733d734b6 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll
@@ -46,26 +46,18 @@ define void @fptosi_v2f64_v2i32(ptr %res, ptr %in){
; LA32-LABEL: fptosi_v2f64_v2i32:
; LA32: # %bb.0:
; LA32-NEXT: vld $vr0, $a1, 0
-; LA32-NEXT: vreplvei.d $vr1, $vr0, 0
-; LA32-NEXT: ftintrz.w.d $fa1, $fa1
-; LA32-NEXT: vreplvei.d $vr0, $vr0, 1
-; LA32-NEXT: ftintrz.w.d $fa0, $fa0
-; LA32-NEXT: fst.s $fa0, $a0, 4
-; LA32-NEXT: fst.s $fa1, $a0, 0
+; LA32-NEXT: vftintrz.w.d $vr0, $vr0, $vr0
+; LA32-NEXT: vpickve2gr.w $a1, $vr0, 1
+; LA32-NEXT: st.w $a1, $a0, 4
+; LA32-NEXT: vpickve2gr.w $a1, $vr0, 0
+; LA32-NEXT: st.w $a1, $a0, 0
; LA32-NEXT: ret
;
; LA64-LABEL: fptosi_v2f64_v2i32:
; LA64: # %bb.0:
; LA64-NEXT: vld $vr0, $a1, 0
-; LA64-NEXT: vreplvei.d $vr1, $vr0, 0
-; LA64-NEXT: ftintrz.w.d $fa1, $fa1
-; LA64-NEXT: movfr2gr.s $a1, $fa1
-; LA64-NEXT: vinsgr2vr.w $vr1, $a1, 0
-; LA64-NEXT: vreplvei.d $vr0, $vr0, 1
-; LA64-NEXT: ftintrz.w.d $fa0, $fa0
-; LA64-NEXT: movfr2gr.s $a1, $fa0
-; LA64-NEXT: vinsgr2vr.w $vr1, $a1, 1
-; LA64-NEXT: vstelm.d $vr1, $a0, 0, 0
+; LA64-NEXT: vftintrz.w.d $vr0, $vr0, $vr0
+; LA64-NEXT: vstelm.d $vr0, $a0, 0, 0
; LA64-NEXT: ret
%v0 = load <2 x double>, ptr %in
%v1 = fptosi <2 x double> %v0 to <2 x i32>
@@ -78,46 +70,16 @@ define void @fptosi_v4f64_v4i32(ptr %res, ptr %in){
; LA32: # %bb.0:
; LA32-NEXT: vld $vr0, $a1, 0
; LA32-NEXT: vld $vr1, $a1, 16
-; LA32-NEXT: vreplvei.d $vr2, $vr0, 0
-; LA32-NEXT: ftintrz.w.d $fa2, $fa2
-; LA32-NEXT: movfr2gr.s $a1, $fa2
-; LA32-NEXT: vinsgr2vr.w $vr2, $a1, 0
-; LA32-NEXT: vreplvei.d $vr0, $vr0, 1
-; LA32-NEXT: ftintrz.w.d $fa0, $fa0
-; LA32-NEXT: movfr2gr.s $a1, $fa0
-; LA32-NEXT: vinsgr2vr.w $vr2, $a1, 1
-; LA32-NEXT: vreplvei.d $vr0, $vr1, 0
-; LA32-NEXT: ftintrz.w.d $fa0, $fa0
-; LA32-NEXT: movfr2gr.s $a1, $fa0
-; LA32-NEXT: vinsgr2vr.w $vr2, $a1, 2
-; LA32-NEXT: vreplvei.d $vr0, $vr1, 1
-; LA32-NEXT: ftintrz.w.d $fa0, $fa0
-; LA32-NEXT: movfr2gr.s $a1, $fa0
-; LA32-NEXT: vinsgr2vr.w $vr2, $a1, 3
-; LA32-NEXT: vst $vr2, $a0, 0
+; LA32-NEXT: vftintrz.w.d $vr0, $vr1, $vr0
+; LA32-NEXT: vst $vr0, $a0, 0
; LA32-NEXT: ret
;
; LA64-LABEL: fptosi_v4f64_v4i32:
; LA64: # %bb.0:
; LA64-NEXT: vld $vr0, $a1, 0
; LA64-NEXT: vld $vr1, $a1, 16
-; LA64-NEXT: vreplvei.d $vr2, $vr0, 0
-; LA64-NEXT: ftintrz.w.d $fa2, $fa2
-; LA64-NEXT: movfr2gr.s $a1, $fa2
-; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 0
-; LA64-NEXT: vreplvei.d $vr0, $vr0, 1
-; LA64-NEXT: ftintrz.w.d $fa0, $fa0
-; LA64-NEXT: movfr2gr.s $a1, $fa0
-; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 1
-; LA64-NEXT: vreplvei.d $vr0, $vr1, 0
-; LA64-NEXT: ftintrz.w.d $fa0, $fa0
-; LA64-NEXT: movfr2gr.s $a1, $fa0
-; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 2
-; LA64-NEXT: vreplvei.d $vr0, $vr1, 1
-; LA64-NEXT: ftintrz.w.d $fa0, $fa0
-; LA64-NEXT: movfr2gr.s $a1, $fa0
-; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 3
-; LA64-NEXT: vst $vr2, $a0, 0
+; LA64-NEXT: vftintrz.w.d $vr0, $vr1, $vr0
+; LA64-NEXT: vst $vr0, $a0, 0
; LA64-NEXT: ret
%v0 = load <4 x double>, ptr %in
%v1 = fptosi <4 x double> %v0 to <4 x i32>
diff --git a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll
index c2ead7f2dfe33..28aac2c042cc3 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll
@@ -46,50 +46,19 @@ define void @fptoui_v2f64_v2i32(ptr %res, ptr %in){
; LA32-LABEL: fptoui_v2f64_v2i32:
; LA32: # %bb.0:
; LA32-NEXT: vld $vr0, $a1, 0
-; LA32-NEXT: vreplvei.d $vr1, $vr0, 0
-; LA32-NEXT: movgr2fr.w $fa2, $zero
-; LA32-NEXT: lu12i.w $a1, 269824
-; LA32-NEXT: movgr2frh.w $fa2, $a1
-; LA32-NEXT: fcmp.clt.d $fcc0, $fa1, $fa2
-; LA32-NEXT: fsub.d $fa3, $fa1, $fa2
-; LA32-NEXT: ftintrz.w.d $fa3, $fa3
-; LA32-NEXT: movfr2gr.s $a1, $fa3
-; LA32-NEXT: lu12i.w $a2, -524288
-; LA32-NEXT: xor $a1, $a1, $a2
-; LA32-NEXT: movcf2gr $a3, $fcc0
-; LA32-NEXT: masknez $a1, $a1, $a3
-; LA32-NEXT: ftintrz.w.d $fa1, $fa1
-; LA32-NEXT: movfr2gr.s $a4, $fa1
-; LA32-NEXT: maskeqz $a3, $a4, $a3
-; LA32-NEXT: or $a1, $a3, $a1
-; LA32-NEXT: vreplvei.d $vr0, $vr0, 1
-; LA32-NEXT: fcmp.clt.d $fcc0, $fa0, $fa2
-; LA32-NEXT: fsub.d $fa1, $fa0, $fa2
-; LA32-NEXT: ftintrz.w.d $fa1, $fa1
-; LA32-NEXT: movfr2gr.s $a3, $fa1
-; LA32-NEXT: xor $a2, $a3, $a2
-; LA32-NEXT: movcf2gr $a3, $fcc0
-; LA32-NEXT: masknez $a2, $a2, $a3
-; LA32-NEXT: ftintrz.w.d $fa0, $fa0
-; LA32-NEXT: movfr2gr.s $a4, $fa0
-; LA32-NEXT: maskeqz $a3, $a4, $a3
-; LA32-NEXT: or $a2, $a3, $a2
-; LA32-NEXT: st.w $a2, $a0, 4
+; LA32-NEXT: vftintrz.l.d $vr0, $vr0
+; LA32-NEXT: vpickve2gr.w $a1, $vr0, 2
+; LA32-NEXT: st.w $a1, $a0, 4
+; LA32-NEXT: vpickve2gr.w $a1, $vr0, 0
; LA32-NEXT: st.w $a1, $a0, 0
; LA32-NEXT: ret
;
; LA64-LABEL: fptoui_v2f64_v2i32:
; LA64: # %bb.0:
; LA64-NEXT: vld $vr0, $a1, 0
-; LA64-NEXT: vreplvei.d $vr1, $vr0, 0
-; LA64-NEXT: ftintrz.l.d $fa1, $fa1
-; LA64-NEXT: movfr2gr.d $a1, $fa1
-; LA64-NEXT: vinsgr2vr.w $vr1, $a1, 0
-; LA64-NEXT: vreplvei.d $vr0, $vr0, 1
-; LA64-NEXT: ftintrz.l.d $fa0, $fa0
-; LA64-NEXT: movfr2gr.d $a1, $fa0
-; LA64-NEXT: vinsgr2vr.w $vr1, $a1, 1
-; LA64-NEXT: vstelm.d $vr1, $a0, 0, 0
+; LA64-NEXT: vftintrz.l.d $vr0, $vr0
+; LA64-NEXT: vshuf4i.w $vr0, $vr0, 8
+; LA64-NEXT: vstelm.d $vr0, $a0, 0, 0
; LA64-NEXT: ret
%v0 = load <2 x double>, ptr %in
%v1 = fptoui <2 x double> %v0 to <2 x i32>
@@ -102,62 +71,9 @@ define void @fptoui_v4f64_v4i32(ptr %res, ptr %in){
; LA32: # %bb.0:
; LA32-NEXT: vld $vr0, $a1, 0
; LA32-NEXT: vld $vr1, $a1, 16
-; LA32-NEXT: vreplvei.d $vr2, $vr0, 1
-; LA32-NEXT: movgr2fr.w $fa3, $zero
-; LA32-NEXT: lu12i.w $a1, 269824
-; LA32-NEXT: movgr2frh.w $fa3, $a1
-; LA32-NEXT: fcmp.clt.d $fcc0, $fa2, $fa3
-; LA32-NEXT: fsub.d $fa4, $fa2, $fa3
-; LA32-NEXT: ftintrz.w.d $fa4, $fa4
-; LA32-NEXT: movfr2gr.s $a1, $fa4
-; LA32-NEXT: lu12i.w $a2, -524288
-; LA32-NEXT: xor $a1, $a1, $a2
-; LA32-NEXT: movcf2gr $a3, $fcc0
-; LA32-NEXT: masknez $a1, $a1, $a3
-; LA32-NEXT: ftintrz.w.d $fa2, $fa2
-; LA32-NEXT: movfr2gr.s $a4, $fa2
-; LA32-NEXT: maskeqz $a3, $a4, $a3
-; LA32-NEXT: or $a1, $a3, $a1
-; LA32-NEXT: vreplvei.d $vr0, $vr0, 0
-; LA32-NEXT: fcmp.clt.d $fcc0, $fa0, $fa3
-; LA32-NEXT: fsub.d $fa2, $fa0, $fa3
-; LA32-NEXT: ftintrz.w.d $fa2, $fa2
-; LA32-NEXT: movfr2gr.s $a3, $fa2
-; LA32-NEXT: xor $a3, $a3, $a2
-; LA32-NEXT: movcf2gr $a4, $fcc0
-; LA32-NEXT: masknez $a3, $a3, $a4
-; LA32-NEXT: ftintrz.w.d $fa0, $fa0
-; LA32-NEXT: movfr2gr.s $a5, $fa0
-; LA32-NEXT: maskeqz $a4, $a5, $a4
-; LA32-NEXT: or $a3, $a4, $a3
-; LA32-NEXT: vinsgr2vr.w $vr0, $a3, 0
-; LA32-NEXT: vinsgr2vr.w $vr0, $a1, 1
-; LA32-NEXT: vreplvei.d $vr2, $vr1, 0
-; LA32-NEXT: fcmp.clt.d $fcc0, $fa2, $fa3
-; LA32-NEXT: fsub.d $fa4, $fa2, $fa3
-; LA32-NEXT: ftintrz.w.d $fa4, $fa4
-; LA32-NEXT: movfr2gr.s $a1, $fa4
-; LA32-NEXT: xor $a1, $a1, $a2
-; LA32-NEXT: movcf2gr $a3, $fcc0
-; LA32-NEXT: masknez $a1, $a1, $a3
-; LA32-NEXT: ftintrz.w.d $fa2, $fa2
-; LA32-NEXT: movfr2gr.s $a4, $fa2
-; LA32-NEXT: maskeqz $a3, $a4, $a3
-; LA32-NEXT: or $a1, $a3, $a1
-; LA32-NEXT: vinsgr2vr.w $vr0, $a1, 2
-; LA32-NEXT: vreplvei.d $vr1, $vr1, 1
-; LA32-NEXT: fcmp.clt.d $fcc0, $fa1, $fa3
-; LA32-NEXT: fsub.d $fa2, $fa1, $fa3
-; LA32-NEXT: ftintrz.w.d $fa2, $fa2
-; LA32-NEXT: movfr2gr.s $a1, $fa2
-; LA32-NEXT: xor $a1, $a1, $a2
-; LA32-NEXT: movcf2gr $a2, $fcc0
-; LA32-NEXT: masknez $a1, $a1, $a2
-; LA32-NEXT: ftintrz.w.d $fa1, $fa1
-; LA32-NEXT: movfr2gr.s $a3, $fa1
-; LA32-NEXT: maskeqz $a2, $a3, $a2
-; LA32-NEXT: or $a1, $a2, $a1
-; LA32-NEXT: vinsgr2vr.w $vr0, $a1, 3
+; LA32-NEXT: vftintrz.l.d $vr0, $vr0
+; LA32-NEXT: vftintrz.l.d $vr1, $vr1
+; LA32-NEXT: vpickev.w $vr0, $vr1, $vr0
; LA32-NEXT: vst $vr0, $a0, 0
; LA32-NEXT: ret
;
@@ -165,23 +81,10 @@ define void @fptoui_v4f64_v4i32(ptr %res, ptr %in){
; LA64: # %bb.0:
; LA64-NEXT: vld $vr0, $a1, 0
; LA64-NEXT: vld $vr1, $a1, 16
-; LA64-NEXT: vreplvei.d $vr2, $vr0, 0
-; LA64-NEXT: ftintrz.l.d $fa2, $fa2
-; LA64-NEXT: movfr2gr.d $a1, $fa2
-; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 0
-; LA64-NEXT: vreplvei.d $vr0, $vr0, 1
-; LA64-NEXT: ftintrz.l.d $fa0, $fa0
-; LA64-NEXT: movfr2gr.d $a1, $fa0
-; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 1
-; LA64-NEXT: vreplvei.d $vr0, $vr1, 0
-; LA64-NEXT: ftintrz.l.d $fa0, $fa0
-; LA64-NEXT: movfr2gr.d $a1, $fa0
-; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 2
-; LA64-NEXT: vreplvei.d $vr0, $vr1, 1
-; LA64-NEXT: ftintrz.l.d $fa0, $fa0
-; LA64-NEXT: movfr2gr.d $a1, $fa0
-; LA64-NEXT: vinsgr2vr.w $vr2, $a1, 3
-; LA64-NEXT: vst $vr2, $a0, 0
+; LA64-NEXT: vftintrz.l.d $vr0, $vr0
+; LA64-NEXT: vftintrz.l.d $vr1, $vr1
+; LA64-NEXT: vpickev.w $vr0, $vr1, $vr0
+; LA64-NEXT: vst $vr0, $a0, 0
; LA64-NEXT: ret
%v0 = load <4 x double>, ptr %in
%v1 = fptoui <4 x double> %v0 to <4 x i32>
More information about the llvm-commits
mailing list