[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:59 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-loongarch
Author: lrzlin
<details>
<summary>Changes</summary>
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
---
Patch is 21.77 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/201569.diff
7 Files Affected:
- (modified) llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp (+102)
- (modified) llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td (+4)
- (modified) llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td (+9)
- (modified) llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll (+17-3)
- (modified) llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll (+94-29)
- (modified) llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptosi.ll (+73-14)
- (modified) llvm/test/CodeGen/LoongArch/lsx/ir-instruction/fptoui.ll (+78-14)
``````````diff
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 5b63ef3e53a4c..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
@@ -43,6 +42,21 @@ 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, 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>
+ 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..4989733d734b6 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,66 @@ 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: 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: 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>
+ 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: 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: 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>
+ 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..28aac2c042cc3 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,71 @@ 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: ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/201569
More information about the llvm-commits
mailing list