[llvm] 80723e0 - Reland: [LoongArch] Custom scalar UINT_TO_FP and FP_TO_UINT with LSX instructions (#206655)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 30 18:33:19 PDT 2026
Author: lrzlin
Date: 2026-07-01T09:33:14+08:00
New Revision: 80723e01f328a09e7e8374d4f61822288daabf9c
URL: https://github.com/llvm/llvm-project/commit/80723e01f328a09e7e8374d4f61822288daabf9c
DIFF: https://github.com/llvm/llvm-project/commit/80723e01f328a09e7e8374d4f61822288daabf9c.diff
LOG: Reland: [LoongArch] Custom scalar UINT_TO_FP and FP_TO_UINT with LSX instructions (#206655)
Using `vftintrz.lu.d` for converting scalar double/float values to
unsigned 64-bit integers, and `vffint.d.lu` vice versa.
Remove incorrect uint64 to float conversion, which is suffered
from double-rounding issue.
Added:
Modified:
llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
llvm/lib/Target/LoongArch/LoongArchISelLowering.h
llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 187f1791661a3..9dc6d23711ec1 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -364,6 +364,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setOperationAction({ISD::SINT_TO_FP, ISD::UINT_TO_FP}, VT, Legal);
setOperationAction({ISD::FP_TO_SINT, ISD::FP_TO_UINT}, VT, Legal);
}
+ setOperationAction(ISD::UINT_TO_FP, GRLenVT, Custom);
for (MVT VT : {MVT::v4f32, MVT::v2f64}) {
setOperationAction({ISD::FADD, ISD::FSUB}, VT, Legal);
setOperationAction({ISD::FMUL, ISD::FDIV}, VT, Legal);
@@ -602,6 +603,8 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
return lowerConstantPool(Op, DAG);
case ISD::FP_TO_SINT:
return lowerFP_TO_SINT(Op, DAG);
+ case ISD::FP_TO_UINT:
+ return lowerFP_TO_UINT(Op, DAG);
case ISD::BITCAST:
return lowerBITCAST(Op, DAG);
case ISD::UINT_TO_FP:
@@ -4170,11 +4173,31 @@ SDValue LoongArchTargetLowering::lowerVASTART(SDValue Op,
SDValue LoongArchTargetLowering::lowerUINT_TO_FP(SDValue Op,
SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+ SDValue Op0 = Op.getOperand(0);
+ EVT VT = Op.getValueType();
+ EVT Op0VT = Op0.getValueType();
+
+ if ((DAG.SignBitIsZero(Op0) || Op->getFlags().hasNonNeg()) &&
+ !isOperationLegal(ISD::UINT_TO_FP, Op0VT) &&
+ isOperationLegal(ISD::SINT_TO_FP, Op0VT))
+ return DAG.getNode(ISD::SINT_TO_FP, DL, VT, Op0);
+
+ // We can't do uint64 -> double -> float because of double-rounding issue.
+ if (Subtarget.hasExtLSX() && Op0VT == MVT::i64 && VT == MVT::f64) {
+ Op0 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2i64, Op0);
+ SDValue Conv = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::v2f64, Op0);
+ Conv = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f64, Conv,
+ DAG.getIntPtrConstant(0, DL));
+ return Conv;
+ }
+
+ if (!Subtarget.is64Bit() || !Subtarget.hasBasicF() || Subtarget.hasBasicD())
+ return SDValue();
+
assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
!Subtarget.hasBasicD() && "unexpected target features");
- SDLoc DL(Op);
- SDValue Op0 = Op.getOperand(0);
if (Op0->getOpcode() == ISD::AND) {
auto *C = dyn_cast<ConstantSDNode>(Op0.getOperand(1));
if (C && C->getZExtValue() < UINT64_C(0xFFFFFFFF))
@@ -4268,6 +4291,30 @@ SDValue LoongArchTargetLowering::lowerFP_TO_SINT(SDValue Op,
return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Trunc);
}
+SDValue LoongArchTargetLowering::lowerFP_TO_UINT(SDValue Op,
+ SelectionDAG &DAG) const {
+ if (!Subtarget.hasExtLSX())
+ return SDValue();
+
+ SDLoc DL(Op);
+ SDValue Src = Op.getOperand(0);
+ EVT VT = Op.getValueType();
+ EVT SrcVT = Src.getValueType();
+
+ if (VT != MVT::i64)
+ return SDValue();
+
+ if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
+ return SDValue();
+
+ if (SrcVT == MVT::f32)
+ Src = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, Src);
+ Src = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2f64, Src);
+ SDValue Conv = DAG.getNode(ISD::FP_TO_UINT, DL, MVT::v2i64, Src);
+ return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Conv,
+ DAG.getIntPtrConstant(0, DL));
+}
+
static SDValue getTargetNode(GlobalAddressSDNode *N, SDLoc DL, EVT Ty,
SelectionDAG &DAG, unsigned Flags) {
return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 96dc3df7f7a27..8d9ec6020478b 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -226,6 +226,7 @@ class LoongArchTargetLowering : public TargetLowering {
SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
index ef211139afdf5..ef6b8fdb86ce7 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
@@ -174,20 +174,9 @@ define i64 @convert_double_to_u64(double %a) nounwind {
;
; LA64-LABEL: convert_double_to_u64:
; LA64: # %bb.0:
-; LA64-NEXT: lu52i.d $a0, $zero, 1086
-; LA64-NEXT: movgr2fr.d $fa1, $a0
-; LA64-NEXT: fcmp.clt.d $fcc0, $fa0, $fa1
-; LA64-NEXT: fsub.d $fa1, $fa0, $fa1
-; LA64-NEXT: ftintrz.l.d $fa1, $fa1
-; LA64-NEXT: movfr2gr.d $a0, $fa1
-; LA64-NEXT: lu52i.d $a1, $zero, -2048
-; LA64-NEXT: xor $a0, $a0, $a1
-; LA64-NEXT: movcf2gr $a1, $fcc0
-; LA64-NEXT: masknez $a0, $a0, $a1
-; LA64-NEXT: ftintrz.l.d $fa0, $fa0
-; LA64-NEXT: movfr2gr.d $a2, $fa0
-; LA64-NEXT: maskeqz $a1, $a2, $a1
-; LA64-NEXT: or $a0, $a1, $a0
+; LA64-NEXT: # kill: def $f0_64 killed $f0_64 def $vr0
+; LA64-NEXT: vftintrz.lu.d $vr0, $vr0
+; LA64-NEXT: vpickve2gr.d $a0, $vr0, 0
; LA64-NEXT: ret
%1 = fptoui double %a to i64
ret i64 %1
@@ -261,18 +250,10 @@ define double @convert_u64_to_double(i64 %a) nounwind {
;
; LA64-LABEL: convert_u64_to_double:
; LA64: # %bb.0:
-; LA64-NEXT: srli.d $a1, $a0, 32
-; LA64-NEXT: lu52i.d $a2, $zero, 1107
-; LA64-NEXT: or $a1, $a1, $a2
-; LA64-NEXT: movgr2fr.d $fa0, $a1
-; LA64-NEXT: lu12i.w $a1, 256
-; LA64-NEXT: lu52i.d $a1, $a1, 1107
-; LA64-NEXT: movgr2fr.d $fa1, $a1
-; LA64-NEXT: fsub.d $fa0, $fa0, $fa1
-; LA64-NEXT: lu12i.w $a1, 275200
-; LA64-NEXT: bstrins.d $a0, $a1, 63, 32
-; LA64-NEXT: movgr2fr.d $fa1, $a0
-; LA64-NEXT: fadd.d $fa0, $fa1, $fa0
+; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0
+; LA64-NEXT: vffint.d.lu $vr0, $vr0
+; LA64-NEXT: vreplvei.d $vr0, $vr0, 0
+; LA64-NEXT: # kill: def $f0_64 killed $f0_64 killed $vr0
; LA64-NEXT: ret
%1 = uitofp i64 %a to double
ret double %1
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
index 8328bb02cf8b5..0c8641b9833f9 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
@@ -283,20 +283,9 @@ define i64 @convert_float_to_u64(float %a) nounwind {
;
; LA64D-LABEL: convert_float_to_u64:
; LA64D: # %bb.0:
-; LA64D-NEXT: lu12i.w $a0, 389120
-; LA64D-NEXT: movgr2fr.w $fa1, $a0
-; LA64D-NEXT: fcmp.clt.s $fcc0, $fa0, $fa1
-; LA64D-NEXT: fsub.s $fa1, $fa0, $fa1
-; LA64D-NEXT: ftintrz.l.s $fa1, $fa1
-; LA64D-NEXT: movfr2gr.d $a0, $fa1
-; LA64D-NEXT: lu52i.d $a1, $zero, -2048
-; LA64D-NEXT: xor $a0, $a0, $a1
-; LA64D-NEXT: movcf2gr $a1, $fcc0
-; LA64D-NEXT: masknez $a0, $a0, $a1
-; LA64D-NEXT: ftintrz.l.s $fa0, $fa0
-; LA64D-NEXT: movfr2gr.d $a2, $fa0
-; LA64D-NEXT: maskeqz $a1, $a2, $a1
-; LA64D-NEXT: or $a0, $a1, $a0
+; LA64D-NEXT: fcvt.d.s $fa0, $fa0
+; LA64D-NEXT: vftintrz.lu.d $vr0, $vr0
+; LA64D-NEXT: vpickve2gr.d $a0, $vr0, 0
; LA64D-NEXT: ret
%1 = fptoui float %a to i64
ret i64 %1
More information about the llvm-commits
mailing list