[llvm] [Mips] Add lowerConstantFP to optimize some floating load instrs to mtc1+mthc1 (PR #196226)
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 6 20:26:25 PDT 2026
https://github.com/yingopq created https://github.com/llvm/llvm-project/pull/196226
Fix #180873.
>From 0ffda1f6db43c1d54dc956ba08a6ec463e98e8b8 Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang at oss.cipunited.com>
Date: Thu, 7 May 2026 11:14:45 +0800
Subject: [PATCH] [Mips] Add lowerConstantFP to optimize some floating load
instrs to mtc1+mthc1
Fix #180873.
---
llvm/lib/Target/Mips/MipsISelLowering.cpp | 42 +++++++++++++++++++++++
llvm/lib/Target/Mips/MipsISelLowering.h | 1 +
llvm/lib/Target/Mips/MipsInstrFPU.td | 10 ++++++
llvm/test/CodeGen/Mips/cconv/vector.ll | 22 +++++-------
llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll | 28 +++++++--------
5 files changed, 75 insertions(+), 28 deletions(-)
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 298b525e48cff..6b0703e1e60ae 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -268,6 +268,9 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::FCANONICALIZE, MVT::f64, Custom);
}
+ if (Subtarget.hasMips32r2())
+ setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
+
if (Subtarget.isGP64bit()) {
setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
setOperationAction(ISD::BlockAddress, MVT::i64, Custom);
@@ -1260,6 +1263,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
case ISD::FP_TO_SINT: return lowerFP_TO_SINT(Op, DAG);
case ISD::READCYCLECOUNTER:
return lowerREADCYCLECOUNTER(Op, DAG);
+ case ISD::ConstantFP:
+ return lowerConstantFP(Op, DAG);
}
return SDValue();
}
@@ -2043,6 +2048,43 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwapPartword(
return exitMBB;
}
+SDValue MipsTargetLowering::lowerConstantFP(SDValue Op,
+ SelectionDAG &DAG) const {
+ EVT VT = Op.getValueType();
+ ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Op);
+ const APFloat &FPVal = CFP->getValueAPF();
+
+ if (!isPositionIndependent())
+ return SDValue();
+
+ if (FPVal.isZero())
+ return SDValue();
+
+ SDLoc DL(CFP);
+ APInt INTVal = FPVal.bitcastToAPInt();
+ switch (VT.getSimpleVT().SimpleTy) {
+ default:
+ llvm_unreachable("Unknown floating point type!");
+ break;
+ case MVT::f64: {
+ if (!Subtarget.hasMTHC1() || !Subtarget.hasMips32r2() ||
+ !Subtarget.isFP64bit())
+ return SDValue();
+ uint64_t Bits = INTVal.getZExtValue();
+ uint32_t Lo = Bits & 0xFFFFFFFF;
+ if (Lo != 0 || Bits == 0)
+ return SDValue();
+
+ SDValue ZeroReg = DAG.getConstant(0, DL, MVT::i32);
+ SDValue LowPart = DAG.getNode(MipsISD::MTC1_D64, DL, VT, ZeroReg);
+ SDValue HiReg = DAG.getConstant(INTVal.lshr(32).trunc(32), DL, MVT::i32);
+ return DAG.getNode(MipsISD::MTHC1_D64, DL, VT, LowPart, HiReg);
+ }
+ }
+
+ return SDValue();
+}
+
SDValue MipsTargetLowering::lowerREADCYCLECOUNTER(SDValue Op,
SelectionDAG &DAG) const {
SmallVector<SDValue, 3> Results;
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 806fb59f5ff3e..2f60e885eb67c 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -379,6 +379,7 @@ class TargetRegisterClass;
SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSTRICT_FP_TO_INT(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerConstantFP(SDValue Op, SelectionDAG &DAG) const;
/// isEligibleForTailCallOptimization - Check whether the call is eligible
/// for tail call optimization.
diff --git a/llvm/lib/Target/Mips/MipsInstrFPU.td b/llvm/lib/Target/Mips/MipsInstrFPU.td
index e4370bbeacf44..8a2fc2d831aeb 100644
--- a/llvm/lib/Target/Mips/MipsInstrFPU.td
+++ b/llvm/lib/Target/Mips/MipsInstrFPU.td
@@ -41,6 +41,10 @@ def SDT_MipsExtractElementF64 : SDTypeProfile<1, 2, [SDTCisVT<0, i32>,
def SDT_MipsMTC1_D64 : SDTypeProfile<1, 1, [SDTCisVT<0, f64>,
SDTCisVT<1, i32>]>;
+def SDT_MipsMTHC1_D64 : SDTypeProfile<1, 2, [SDTCisVT<0, f64>,
+ SDTCisVT<1, f64>,
+ SDTCisVT<2, i32>]>;
+
// Floating Point Compare
def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp, [SDNPOutGlue]>;
@@ -63,6 +67,8 @@ def MipsExtractElementF64 : SDNode<"MipsISD::ExtractElementF64",
// Node used to generate an MTC1 i32 to f64 instruction
def MipsMTC1_D64 : SDNode<"MipsISD::MTC1_D64", SDT_MipsMTC1_D64>;
+// Node used to generate an MTHC1 i32 to high half of f64 instruction
+def MipsMTHC1_D64 : SDNode<"MipsISD::MTHC1_D64", SDT_MipsMTHC1_D64>;
// Operand for printing out a condition code.
let PrintMethod = "printFCCOperand", DecoderMethod = "DecodeCondCode" in
@@ -638,6 +644,7 @@ let AdditionalPredicates = [NotInMicroMips] in {
def MTHC1_D64 : MTC1_64_FT<"mthc1", FGR64Opnd, GPR32Opnd, II_MTHC1>,
MFC1_FM<7>, ISA_MIPS32R2, FGR_64 {
let DecoderNamespace = "MipsFP64";
+ let hasSideEffects = 1;
}
let AdditionalPredicates = [IsNotSingleFloat] in {
@@ -1035,6 +1042,9 @@ def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src),
def : MipsPat<(MipsMTC1_D64 GPR32Opnd:$src),
(MTC1_D64 GPR32Opnd:$src)>, ISA_MIPS1, FGR_64;
+def : MipsPat<(MipsMTHC1_D64 FGR64Opnd:$lo, GPR32Opnd:$hi),
+ (MTHC1_D64 FGR64Opnd:$lo, GPR32Opnd:$hi)>, ISA_MIPS32R2, FGR_64;
+
def : MipsPat<(f64 (any_sint_to_fp GPR32Opnd:$src)),
(PseudoCVT_D32_W GPR32Opnd:$src)>, FGR_32;
let AdditionalPredicates = [NotInMicroMips] in {
diff --git a/llvm/test/CodeGen/Mips/cconv/vector.ll b/llvm/test/CodeGen/Mips/cconv/vector.ll
index c64c60ddef73d..65ef76d5e5a9f 100644
--- a/llvm/test/CodeGen/Mips/cconv/vector.ll
+++ b/llvm/test/CodeGen/Mips/cconv/vector.ll
@@ -5652,15 +5652,12 @@ define <4 x float> @mixed_32(<4 x float> %a, i32 %b) {
; MIPS64R5EB: # %bb.0: # %entry
; MIPS64R5EB-NEXT: daddiu $sp, $sp, -16
; MIPS64R5EB-NEXT: .cfi_def_cfa_offset 16
-; MIPS64R5EB-NEXT: lui $1, %hi(%neg(%gp_rel(mixed_32)))
-; MIPS64R5EB-NEXT: daddu $1, $1, $25
-; MIPS64R5EB-NEXT: daddiu $1, $1, %lo(%neg(%gp_rel(mixed_32)))
-; MIPS64R5EB-NEXT: lui $2, 17200
-; MIPS64R5EB-NEXT: sw $2, 8($sp)
+; MIPS64R5EB-NEXT: lui $1, 17200
+; MIPS64R5EB-NEXT: sw $1, 8($sp)
; MIPS64R5EB-NEXT: sll $2, $6, 0
; MIPS64R5EB-NEXT: sw $2, 12($sp)
-; MIPS64R5EB-NEXT: ld $1, %got_page(.LCPI41_0)($1)
-; MIPS64R5EB-NEXT: ldc1 $f0, %got_ofst(.LCPI41_0)($1)
+; MIPS64R5EB-NEXT: mtc1 $zero, $f0
+; MIPS64R5EB-NEXT: mthc1 $1, $f0
; MIPS64R5EB-NEXT: ldc1 $f1, 8($sp)
; MIPS64R5EB-NEXT: sub.d $f0, $f1, $f0
; MIPS64R5EB-NEXT: insert.d $w1[0], $4
@@ -5781,15 +5778,12 @@ define <4 x float> @mixed_32(<4 x float> %a, i32 %b) {
; MIPS64R5EL: # %bb.0: # %entry
; MIPS64R5EL-NEXT: daddiu $sp, $sp, -16
; MIPS64R5EL-NEXT: .cfi_def_cfa_offset 16
-; MIPS64R5EL-NEXT: lui $1, %hi(%neg(%gp_rel(mixed_32)))
-; MIPS64R5EL-NEXT: daddu $1, $1, $25
-; MIPS64R5EL-NEXT: daddiu $1, $1, %lo(%neg(%gp_rel(mixed_32)))
-; MIPS64R5EL-NEXT: lui $2, 17200
-; MIPS64R5EL-NEXT: sw $2, 12($sp)
+; MIPS64R5EL-NEXT: lui $1, 17200
+; MIPS64R5EL-NEXT: sw $1, 12($sp)
; MIPS64R5EL-NEXT: sll $2, $6, 0
; MIPS64R5EL-NEXT: sw $2, 8($sp)
-; MIPS64R5EL-NEXT: ld $1, %got_page(.LCPI41_0)($1)
-; MIPS64R5EL-NEXT: ldc1 $f0, %got_ofst(.LCPI41_0)($1)
+; MIPS64R5EL-NEXT: mtc1 $zero, $f0
+; MIPS64R5EL-NEXT: mthc1 $1, $f0
; MIPS64R5EL-NEXT: ldc1 $f1, 8($sp)
; MIPS64R5EL-NEXT: sub.d $f0, $f1, $f0
; MIPS64R5EL-NEXT: insert.d $w1[0], $4
diff --git a/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll b/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll
index 089b5bfab8fd9..33e3ea62ca44a 100644
--- a/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll
+++ b/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll
@@ -379,8 +379,8 @@ define void @uitofp(i32 %a) {
; MIPS32-NEXT: lui $2, 17200
; MIPS32-NEXT: sw $2, 4($sp)
; MIPS32-NEXT: sw $4, 0($sp)
-; MIPS32-NEXT: lw $2, %got($CPI5_0)($1)
-; MIPS32-NEXT: ldc1 $f0, %lo($CPI5_0)($2)
+; MIPS32-NEXT: mtc1 $zero, $f0
+; MIPS32-NEXT: mthc1 $2, $f0
; MIPS32-NEXT: ldc1 $f1, 0($sp)
; MIPS32-NEXT: sub.d $f0, $f1, $f0
; MIPS32-NEXT: mfc1 $2, $f0
@@ -405,10 +405,10 @@ define void @uitofp(i32 %a) {
; MIPS64R5-N32-NEXT: addiu $1, $1, %lo(%neg(%gp_rel(uitofp)))
; MIPS64R5-N32-NEXT: lui $2, 17200
; MIPS64R5-N32-NEXT: sw $2, 12($sp)
-; MIPS64R5-N32-NEXT: sll $2, $4, 0
-; MIPS64R5-N32-NEXT: sw $2, 8($sp)
-; MIPS64R5-N32-NEXT: lw $2, %got_page(.LCPI5_0)($1)
-; MIPS64R5-N32-NEXT: ldc1 $f0, %got_ofst(.LCPI5_0)($2)
+; MIPS64R5-N32-NEXT: sll $3, $4, 0
+; MIPS64R5-N32-NEXT: sw $3, 8($sp)
+; MIPS64R5-N32-NEXT: mtc1 $zero, $f0
+; MIPS64R5-N32-NEXT: mthc1 $2, $f0
; MIPS64R5-N32-NEXT: ldc1 $f1, 8($sp)
; MIPS64R5-N32-NEXT: sub.d $f0, $f1, $f0
; MIPS64R5-N32-NEXT: dmfc1 $2, $f0
@@ -430,10 +430,10 @@ define void @uitofp(i32 %a) {
; MIPS64R5-N64-NEXT: daddiu $1, $1, %lo(%neg(%gp_rel(uitofp)))
; MIPS64R5-N64-NEXT: lui $2, 17200
; MIPS64R5-N64-NEXT: sw $2, 12($sp)
-; MIPS64R5-N64-NEXT: sll $2, $4, 0
-; MIPS64R5-N64-NEXT: sw $2, 8($sp)
-; MIPS64R5-N64-NEXT: ld $2, %got_page(.LCPI5_0)($1)
-; MIPS64R5-N64-NEXT: ldc1 $f0, %got_ofst(.LCPI5_0)($2)
+; MIPS64R5-N64-NEXT: sll $3, $4, 0
+; MIPS64R5-N64-NEXT: sw $3, 8($sp)
+; MIPS64R5-N64-NEXT: mtc1 $zero, $f0
+; MIPS64R5-N64-NEXT: mthc1 $2, $f0
; MIPS64R5-N64-NEXT: ldc1 $f1, 8($sp)
; MIPS64R5-N64-NEXT: sub.d $f0, $f1, $f0
; MIPS64R5-N64-NEXT: dmfc1 $2, $f0
@@ -456,8 +456,8 @@ define void @uitofp(i32 %a) {
; MIPSR6-N32-NEXT: lui $2, 17200
; MIPSR6-N32-NEXT: sw $2, 12($sp)
; MIPSR6-N32-NEXT: sw $4, 8($sp)
-; MIPSR6-N32-NEXT: lw $2, %got_page(.LCPI5_0)($1)
-; MIPSR6-N32-NEXT: ldc1 $f0, %got_ofst(.LCPI5_0)($2)
+; MIPSR6-N32-NEXT: mtc1 $zero, $f0
+; MIPSR6-N32-NEXT: mthc1 $2, $f0
; MIPSR6-N32-NEXT: ldc1 $f1, 8($sp)
; MIPSR6-N32-NEXT: sub.d $f0, $f1, $f0
; MIPSR6-N32-NEXT: dmfc1 $2, $f0
@@ -480,8 +480,8 @@ define void @uitofp(i32 %a) {
; MIPSR6-N64-NEXT: lui $2, 17200
; MIPSR6-N64-NEXT: sw $2, 12($sp)
; MIPSR6-N64-NEXT: sw $4, 8($sp)
-; MIPSR6-N64-NEXT: ld $2, %got_page(.LCPI5_0)($1)
-; MIPSR6-N64-NEXT: ldc1 $f0, %got_ofst(.LCPI5_0)($2)
+; MIPSR6-N64-NEXT: mtc1 $zero, $f0
+; MIPSR6-N64-NEXT: mthc1 $2, $f0
; MIPSR6-N64-NEXT: ldc1 $f1, 8($sp)
; MIPSR6-N64-NEXT: sub.d $f0, $f1, $f0
; MIPSR6-N64-NEXT: dmfc1 $2, $f0
More information about the llvm-commits
mailing list