[llvm] [LoongArch] Combine FP_TO_UINT/FP_TO_SINT with [X]VFTINTRZ instruction (PR #201569)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 14 09:42:49 PDT 2026


https://github.com/lrzlin updated https://github.com/llvm/llvm-project/pull/201569

>From 6fe5c4ca9023a747de831e5c1ffd647bcc546af3 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   |  20 +++
 .../LoongArch/lsx/ir-instruction/fptosi.ll    |  64 +++++++-
 .../LoongArch/lsx/ir-instruction/fptoui.ll    | 151 +++++++++++++++++-
 4 files changed, 251 insertions(+), 4 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..2ef774d93a619 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll
@@ -43,6 +43,26 @@ define void @fptoui_v4f64_v4i32(ptr %res, ptr %in){
   ret void
 }
 
+define void @fptoui_v8f64_v8i32(ptr %res, ptr %in){
+; CHECK-LABEL: fptoui_v8f64_v8i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvld $xr0, $a1, 32
+; CHECK-NEXT:    xvld $xr1, $a1, 0
+; CHECK-NEXT:    xvftintrz.lu.d $xr0, $xr0
+; CHECK-NEXT:    xvpermi.d $xr2, $xr0, 238
+; CHECK-NEXT:    xvpickev.w $xr0, $xr2, $xr0
+; CHECK-NEXT:    xvftintrz.lu.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 = 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:
diff --git a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll
index 7ea6d7431670e..ce55d2f9b31b2 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll
@@ -1,6 +1,6 @@
 ; 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-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx < %s | FileCheck %s --check-prefixes=CHECK,LA64
 
 define void @fptosi_v4f32_v4i32(ptr %res, ptr %in){
 ; CHECK-LABEL: fptosi_v4f32_v4i32:
@@ -27,3 +27,63 @@ define void @fptosi_v2f64_v2i64(ptr %res, ptr %in){
   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){
+; CHECK-LABEL: fptosi_v4f64_v4i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vld $vr0, $a1, 0
+; CHECK-NEXT:    vld $vr1, $a1, 16
+; CHECK-NEXT:    vreplvei.d $vr2, $vr0, 0
+; CHECK-NEXT:    ftintrz.w.d $fa2, $fa2
+; CHECK-NEXT:    movfr2gr.s $a1, $fa2
+; CHECK-NEXT:    vinsgr2vr.w $vr2, $a1, 0
+; CHECK-NEXT:    vreplvei.d $vr0, $vr0, 1
+; CHECK-NEXT:    ftintrz.w.d $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a1, $fa0
+; CHECK-NEXT:    vinsgr2vr.w $vr2, $a1, 1
+; CHECK-NEXT:    vreplvei.d $vr0, $vr1, 0
+; CHECK-NEXT:    ftintrz.w.d $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a1, $fa0
+; CHECK-NEXT:    vinsgr2vr.w $vr2, $a1, 2
+; CHECK-NEXT:    vreplvei.d $vr0, $vr1, 1
+; CHECK-NEXT:    ftintrz.w.d $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a1, $fa0
+; CHECK-NEXT:    vinsgr2vr.w $vr2, $a1, 3
+; CHECK-NEXT:    vst $vr2, $a0, 0
+; CHECK-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..f55f2ae6f5471 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll
@@ -1,6 +1,6 @@
 ; 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-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx < %s | FileCheck %s --check-prefixes=CHECK,LA64
 
 define void @fptoui_v4f32_v4i32(ptr %res, ptr %in){
 ; CHECK-LABEL: fptoui_v4f32_v4i32:
@@ -27,3 +27,150 @@ define void @fptoui_v2f64_v2i64(ptr %res, ptr %in){
   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 8240e17373078adf41be92a2e0a2c95298be7fa9 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       |  96 ++++++++++++
 .../LoongArch/LoongArchLASXInstrInfo.td       |   4 +
 .../Target/LoongArch/LoongArchLSXInstrInfo.td |   9 ++
 .../LoongArch/lasx/ir-instruction/fptosi.ll   |  20 +--
 .../LoongArch/lsx/ir-instruction/fptosi.ll    |  41 ++----
 .../LoongArch/lsx/ir-instruction/fptoui.ll    | 139 ++----------------
 6 files changed, 141 insertions(+), 168 deletions(-)

diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 561064b3e1090..382067aae9ed0 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,97 @@ 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) {
+    // LASX already has pattern for double convert to uint32.
+    if (Subtarget.hasExtLASX())
+      return SDValue();
+    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 BlockNumElts = BlockBits / 64;
+  MVT BlockVT = MVT::getVectorVT(MVT::f64, BlockNumElts);
+  if (Src.getOpcode() == ISD::CONCAT_VECTORS &&
+      Src.getOperand(0).getValueType() == BlockVT) {
+    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, BlockVT, Src,
+                      DAG.getVectorIdxConstant(i * BlockNumElts, DL)));
+  } else {
+    BlockBits = SrcBits;
+    Blocks.push_back(Src);
+  }
+
+  MVT NativeVT = BlockBits == 256 ? MVT::v8i32 : MVT::v4i32;
+  SmallVector<SDValue, 4> Parts;
+  for (unsigned i = 0; i < Blocks.size(); i += 2) {
+    SDValue Lo = Blocks[i];
+    SDValue Hi = Blocks.size() > 1 ? Blocks[i + 1] : Lo;
+    SDValue Res = DAG.getNode(LoongArchISD::VFTINTRZ, DL, NativeVT, Hi, Lo);
+
+    if (BlockBits == 256) {
+      SDValue Undef = DAG.getUNDEF(Res.getValueType());
+      SmallVector<int, 8> Mask = {0, 1, 4, 5, 2, 3, 6, 7};
+      Res = DAG.getVectorShuffle(Res.getValueType(), DL, Res, Undef, Mask);
+      Res = DAG.getBitcast(NativeVT, Res);
+    }
+
+    Parts.push_back(Res);
+  }
+
+  if (Blocks.size() == 1)
+    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 +8162,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..a7829eb7215d8 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, 8
 ; 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 ce55d2f9b31b2..77faa98e4247b 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll
@@ -32,26 +32,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>
@@ -64,23 +56,8 @@ define void @fptosi_v4f64_v4i32(ptr %res, ptr %in){
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    vld $vr0, $a1, 0
 ; CHECK-NEXT:    vld $vr1, $a1, 16
-; CHECK-NEXT:    vreplvei.d $vr2, $vr0, 0
-; CHECK-NEXT:    ftintrz.w.d $fa2, $fa2
-; CHECK-NEXT:    movfr2gr.s $a1, $fa2
-; CHECK-NEXT:    vinsgr2vr.w $vr2, $a1, 0
-; CHECK-NEXT:    vreplvei.d $vr0, $vr0, 1
-; CHECK-NEXT:    ftintrz.w.d $fa0, $fa0
-; CHECK-NEXT:    movfr2gr.s $a1, $fa0
-; CHECK-NEXT:    vinsgr2vr.w $vr2, $a1, 1
-; CHECK-NEXT:    vreplvei.d $vr0, $vr1, 0
-; CHECK-NEXT:    ftintrz.w.d $fa0, $fa0
-; CHECK-NEXT:    movfr2gr.s $a1, $fa0
-; CHECK-NEXT:    vinsgr2vr.w $vr2, $a1, 2
-; CHECK-NEXT:    vreplvei.d $vr0, $vr1, 1
-; CHECK-NEXT:    ftintrz.w.d $fa0, $fa0
-; CHECK-NEXT:    movfr2gr.s $a1, $fa0
-; CHECK-NEXT:    vinsgr2vr.w $vr2, $a1, 3
-; CHECK-NEXT:    vst $vr2, $a0, 0
+; CHECK-NEXT:    vftintrz.w.d $vr0, $vr1, $vr0
+; CHECK-NEXT:    vst $vr0, $a0, 0
 ; CHECK-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 f55f2ae6f5471..c1ca142c906bf 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll
@@ -32,50 +32,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>
@@ -84,91 +53,15 @@ define void @fptoui_v2f64_v2i32(ptr %res, ptr %in){
 }
 
 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
+; CHECK-LABEL: fptoui_v4f64_v4i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vld $vr0, $a1, 0
+; CHECK-NEXT:    vld $vr1, $a1, 16
+; CHECK-NEXT:    vftintrz.l.d $vr0, $vr0
+; CHECK-NEXT:    vftintrz.l.d $vr1, $vr1
+; CHECK-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; CHECK-NEXT:    vst $vr0, $a0, 0
+; CHECK-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



More information about the llvm-commits mailing list