[llvm] [Mips] Add lowerConstantFP to optimize some floating load instrs to mtc1+mthc1 (PR #196226)

Ying Huang via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 22 02:34:56 PDT 2026


https://github.com/yingopq updated https://github.com/llvm/llvm-project/pull/196226

>From 90e2b0e4ee5d4afbf20fd33b5bf13a0f6e2c35e6 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 1/2] [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 a75960fd2af76..3edb792aca696 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -273,6 +273,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);
@@ -1266,6 +1269,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();
 }
@@ -2098,6 +2103,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 68272cb403b36..298383292f064 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -382,6 +382,7 @@ using TargetRegisterClass = MCRegisterClass;
     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 1555e17572334..b7d5ae9c45d7b 100644
--- a/llvm/lib/Target/Mips/MipsInstrFPU.td
+++ b/llvm/lib/Target/Mips/MipsInstrFPU.td
@@ -47,6 +47,10 @@ def SDT_MipsExtractElementF64_FPR : SDTypeProfile<1, 2, [SDTCisVT<0, f32>,
 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]>;
 
@@ -73,6 +77,8 @@ def MipsExtractElementF64_FPR : SDNode<"MipsISD::ExtractElementF64_FPR",
 // 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
@@ -635,6 +641,7 @@ let AdditionalPredicates = [NotInMicroMips] in {
   def MTHC1_D64 : MTC1_64_FT<"mthc1", FGR64Opnd, GPR32Opnd>,
                   MFC1_FM<7>, ISA_MIPS32R2, FGR_64 {
     let DecoderNamespace = "MipsFP64";
+    let hasSideEffects = 1;
   }
 
   let AdditionalPredicates = [IsNotSingleFloat] in {
@@ -1043,6 +1050,9 @@ def : MipsPat<(setlt (i32 (bitconvert (f32 (fpround FGR64Opnd:$src)))), 0),
           (SLTi (MFHC1_D64 FGR64Opnd:$src), 0)>,
           ISA_MIPS32R2, 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 5cd2b77615fcd..75087792320c1 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 b14c88e231413..93e729eecc806 100644
--- a/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll
+++ b/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll
@@ -324,8 +324,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:    cvt.s.d $f0, $f0
@@ -346,10 +346,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:    cvt.s.d $f0, $f0
@@ -370,10 +370,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:    cvt.s.d $f0, $f0
@@ -395,8 +395,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:    cvt.s.d $f0, $f0
@@ -418,8 +418,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:    cvt.s.d $f0, $f0

>From 5906d332e10a3e0fba2ecb3480d35a5f5ad2a36a Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang at oss.cipunited.com>
Date: Tue, 22 Sep 2026 17:26:49 +0800
Subject: [PATCH 2/2] Optimize the code and reuse existing abstractions

---
 llvm/lib/Target/Mips/MipsISelLowering.cpp | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 3edb792aca696..ea7bc90f01119 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -2130,10 +2130,12 @@ SDValue MipsTargetLowering::lowerConstantFP(SDValue Op,
     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);
+    // TODO: DAG.getConstant(0) should be optimized to avoid generate an extra
+    // instr `addiu $x, $zero, 0`.
+    SDValue Low =
+        DAG.getCopyFromReg(DAG.getEntryNode(), DL, Mips::ZERO, MVT::i32);
+    SDValue Hi = DAG.getConstant(INTVal.extractBits(32, 32), DL, MVT::i32);
+    return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, Low, Hi);
   }
   }
 



More information about the llvm-commits mailing list