[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