[llvm] 5250048 - [Mips] Fix O32 lowering on 64-bit CPUs (#224937)

via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 20 08:49:17 PDT 2026


Author: Jiaxun Yang
Date: 2026-09-20T16:49:09+01:00
New Revision: 52500486a0b723a1d9528e3098901702da837c3d

URL: https://github.com/llvm/llvm-project/commit/52500486a0b723a1d9528e3098901702da837c3d
DIFF: https://github.com/llvm/llvm-project/commit/52500486a0b723a1d9528e3098901702da837c3d.diff

LOG: [Mips] Fix O32 lowering on 64-bit CPUs (#224937)

Use 32-bit GPR lowering for O32 while preserving the selected ISA and
FPR mode. Handle FP64 transfers through the stack when high-half moves
are unavailable.

Added: 
    llvm/test/CodeGen/Mips/cconv/o32-fp64-gpr-moves.ll
    llvm/test/CodeGen/Mips/cconv/o32-mips64.ll

Modified: 
    llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
    llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
    llvm/lib/Target/Mips/MipsSEInstrInfo.cpp
    llvm/lib/Target/Mips/MipsSubtarget.cpp
    llvm/test/CodeGen/Mips/cconv/arguments-float.ll
    llvm/test/CodeGen/Mips/cconv/arguments-struct.ll
    llvm/test/CodeGen/Mips/cconv/arguments-varargs.ll
    llvm/test/CodeGen/Mips/cconv/arguments.ll
    llvm/test/CodeGen/Mips/cconv/callee-saved-float.ll
    llvm/test/CodeGen/Mips/cconv/callee-saved.ll
    llvm/test/CodeGen/Mips/cconv/memory-layout.ll
    llvm/test/CodeGen/Mips/cconv/reserved-space.ll
    llvm/test/CodeGen/Mips/cconv/return-float.ll
    llvm/test/CodeGen/Mips/cconv/return-hard-float.ll
    llvm/test/CodeGen/Mips/cconv/return-struct.ll
    llvm/test/CodeGen/Mips/cconv/return.ll
    llvm/test/CodeGen/Mips/cconv/stack-alignment.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp b/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
index 937e33bd840e6..2aeee5b4e97c9 100644
--- a/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
@@ -277,17 +277,17 @@ bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I,
 }
 
 /// This method expands the same instruction that MipsSEInstrInfo::
-/// expandBuildPairF64 does, for the case when ABI is fpxx and mthc1 is not
-/// available and the case where the ABI is FP64A. It is implemented here
+/// expandBuildPairF64 does, for FPXX/FP64 when mthc1 is not available and
+/// for FP64A. It is implemented here
 /// because frame indexes are eliminated before MipsSEInstrInfo::
 /// expandBuildPairF64 is called.
 bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB,
                                       MachineBasicBlock::iterator I,
                                       bool FP64) const {
-  // For fpxx and when mthc1 is not available, use:
+  // For FPXX/FP64 when mthc1 is not available, use:
   //   spill + reload via ldc1
   //
-  // The case where dmtc1 is available doesn't need to be handled here
+  // The case where 64-bit GPRs can be used doesn't need to be handled here
   // because it never creates a BuildPairF64 node.
   //
   // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence
@@ -306,12 +306,6 @@ bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB,
     Register LoReg = I->getOperand(1).getReg();
     Register HiReg = I->getOperand(2).getReg();
 
-    // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are
-    // the cases where mthc1 is not available). 64-bit architectures and
-    // MIPS32r2 or later can use FGR64 though.
-    assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() ||
-           !Subtarget.isFP64bit());
-
     const TargetRegisterClass *RC = &Mips::GPR32RegClass;
     const TargetRegisterClass *RC2 =
         FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
@@ -331,8 +325,8 @@ bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB,
 }
 
 /// This method expands the same instruction that MipsSEInstrInfo::
-/// expandExtractElementF64 does, for the case when ABI is fpxx and mfhc1 is not
-/// available and the case where the ABI is FP64A. It is implemented here
+/// expandExtractElementF64 does, for FPXX/FP64 when mfhc1 is not available and
+/// for FP64A. It is implemented here
 /// because frame indexes are eliminated before MipsSEInstrInfo::
 /// expandExtractElementF64 is called.
 bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB,
@@ -347,10 +341,10 @@ bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB,
     return true;
   }
 
-  // For fpxx and when mfhc1 is not available, use:
+  // For FPXX/FP64 when mfhc1 is not available, use:
   //   spill + reload via ldc1
   //
-  // The case where dmfc1 is available doesn't need to be handled here
+  // The case where 64-bit GPRs can be used doesn't need to be handled here
   // because it never creates a ExtractElementF64 node.
   //
   // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence
@@ -370,12 +364,6 @@ bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB,
     unsigned N = Op2.getImm();
     int64_t Offset = 4 * (Subtarget.isLittle() ? N : (1 - N));
 
-    // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are
-    // the cases where mfhc1 is not available). 64-bit architectures and
-    // MIPS32r2 or later can use FGR64 though.
-    assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() ||
-           !Subtarget.isFP64bit());
-
     const TargetRegisterClass *RC =
         FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
     const TargetRegisterClass *RC2 = &Mips::GPR32RegClass;

diff  --git a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
index 65cec6aa61cad..e3599e268c88e 100644
--- a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
@@ -162,7 +162,7 @@ void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) {
         break;
       case Mips::BuildPairF64_64:
       case Mips::ExtractElementF64_64:
-        if (!Subtarget->useOddSPReg()) {
+        if (!Subtarget->useOddSPReg() || !Subtarget->hasMTHC1()) {
           MI.addOperand(MachineOperand::CreateReg(Mips::SP, false, true));
           break;
         }

diff  --git a/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp b/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp
index b16341dcec0b9..b2062671142f5 100644
--- a/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp
@@ -856,9 +856,9 @@ void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB,
   unsigned SubIdx = N ? Mips::sub_hi : Mips::sub_lo;
   Register SubReg = getRegisterInfo().getSubReg(SrcReg, SubIdx);
 
-  // FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload
+  // FPXX/FP64 without MFHC1 should have been handled with a spill/reload
   // in MipsSEFrameLowering.cpp.
-  assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2()));
+  assert(!((Subtarget.isABI_FPXX() || FP64) && !Subtarget.hasMTHC1()));
 
   // FP64A (FP64 with nooddspreg) should have been handled with a spill/reload
   // in MipsSEFrameLowering.cpp.
@@ -899,7 +899,7 @@ void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB,
   //   mtc1 Lo, $fp
   //   mthc1 Hi, $fp
   //
-  // Otherwise, for O32 FPXX ABI:
+  // Otherwise, for FPXX/FP64:
   //   spill + reload via ldc1
   // This case is handled by the frame lowering code.
   //
@@ -907,12 +907,12 @@ void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB,
   //   mtc1 Lo, $fp
   //   mtc1 Hi, $fp + 1
   //
-  // The case where dmtc1 is available doesn't need to be handled here
+  // The case where 64-bit GPRs can be used doesn't need to be handled here
   // because it never creates a BuildPairF64 node.
 
-  // FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload
+  // FPXX/FP64 without MTHC1 should have been handled with a spill/reload
   // in MipsSEFrameLowering.cpp.
-  assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2()));
+  assert(!((Subtarget.isABI_FPXX() || FP64) && !Subtarget.hasMTHC1()));
 
   // FP64A (FP64 with nooddspreg) should have been handled with a spill/reload
   // in MipsSEFrameLowering.cpp.

diff  --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp
index 14d507848f2f6..3726a8e04166c 100644
--- a/llvm/lib/Target/Mips/MipsSubtarget.cpp
+++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp
@@ -253,6 +253,11 @@ MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS,
 
   // Parse features string.
   ParseSubtargetFeatures(CPUName, /*TuneCPU*/ CPUName, FS);
+
+  // O32 uses 32-bit GPRs even when the selected CPU supports a 64-bit ISA.
+  if (isABI_O32())
+    IsGP64bit = false;
+
   if (InMips16Mode && !IsSoftFloat)
     InMips16HardFloat = true;
 

diff  --git a/llvm/test/CodeGen/Mips/cconv/arguments-float.ll b/llvm/test/CodeGen/Mips/cconv/arguments-float.ll
index 3a39a29de02fe..c639b3edc79cb 100644
--- a/llvm/test/CodeGen/Mips/cconv/arguments-float.ll
+++ b/llvm/test/CodeGen/Mips/cconv/arguments-float.ll
@@ -1,8 +1,8 @@
 ; RUN: llc -mtriple=mips -relocation-model=static -mattr=+soft-float < %s | FileCheck --check-prefixes=ALL,SYM32,O32 %s
 ; RUN: llc -mtriple=mipsel -relocation-model=static -mattr=+soft-float < %s | FileCheck --check-prefixes=ALL,SYM32,O32 %s
 
-; RUN-TODO: llc -mtriple=mips64 -relocation-model=static -mattr=+soft-float -target-abi o32 < %s | FileCheck --check-prefixes=ALL,SYM32,O32 %s
-; RUN-TODO: llc -mtriple=mips64el -relocation-model=static -mattr=+soft-float -target-abi o32 < %s | FileCheck --check-prefixes=ALL,SYM32,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64 -relocation-model=static -mattr=+soft-float -target-abi o32 < %s | FileCheck --check-prefixes=ALL,SYM32,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el -relocation-model=static -mattr=+soft-float -target-abi o32 < %s | FileCheck --check-prefixes=ALL,SYM32,O32 %s
 
 ; RUN: llc -mtriple=mips64 -relocation-model=static -mattr=+soft-float -target-abi n32 < %s | FileCheck --check-prefixes=ALL,SYM32,NEW %s
 ; RUN: llc -mtriple=mips64el -relocation-model=static -mattr=+soft-float -target-abi n32 < %s | FileCheck --check-prefixes=ALL,SYM32,NEW %s

diff  --git a/llvm/test/CodeGen/Mips/cconv/arguments-struct.ll b/llvm/test/CodeGen/Mips/cconv/arguments-struct.ll
index 371459f5f85b0..6496e2de227ba 100644
--- a/llvm/test/CodeGen/Mips/cconv/arguments-struct.ll
+++ b/llvm/test/CodeGen/Mips/cconv/arguments-struct.ll
@@ -1,8 +1,8 @@
 ; RUN: llc -mtriple=mips-unknown-linux-gnu -relocation-model=static < %s | FileCheck --check-prefixes=ALL,SYM32,O32-BE %s
 ; RUN: llc -mtriple=mipsel-unknown-linux-gnu -relocation-model=static < %s | FileCheck --check-prefixes=ALL,SYM32,O32-LE %s
 
-; RUN-TODO: llc -mtriple=mips64-unknown-linux-gnu -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,SYM32,O32-BE %s
-; RUN-TODO: llc -mtriple=mips64el-unknown-linux-gnu -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,SYM32,O32-LE %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64-unknown-linux-gnu -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,SYM32,O32-BE %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el-unknown-linux-gnu -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,SYM32,O32-LE %s
 
 ; RUN: llc -mtriple=mips64-unknown-linux-gnu -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,SYM32,NEW-BE %s
 ; RUN: llc -mtriple=mips64el-unknown-linux-gnu -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,SYM32,NEW-LE %s

diff  --git a/llvm/test/CodeGen/Mips/cconv/arguments-varargs.ll b/llvm/test/CodeGen/Mips/cconv/arguments-varargs.ll
index 1f97b376c290b..b87d27489bd0f 100644
--- a/llvm/test/CodeGen/Mips/cconv/arguments-varargs.ll
+++ b/llvm/test/CodeGen/Mips/cconv/arguments-varargs.ll
@@ -3,10 +3,10 @@
 ; RUN: llc -mtriple=mipsel-linux -relocation-model=static < %s \
 ; RUN:   | FileCheck --check-prefixes=ALL,O32 %s
 
-; RUN-TODO: llc -mtriple=mips64 -relocation-model=static -target-abi o32 < %s \
-; RUN-TODO:   | FileCheck --check-prefixes=ALL,O32 %s
-; RUN-TODO: llc -mtriple=mips64el -relocation-model=static -target-abi o32 < %s \
-; RUN-TODO:   | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64 -relocation-model=static -target-abi o32 < %s \
+; RUN:   | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el -relocation-model=static -target-abi o32 < %s \
+; RUN:   | FileCheck --check-prefixes=ALL,O32 %s
 
 ; RUN: llc -mtriple=mips64-linux -relocation-model=static -target-abi n32 < %s \
 ; RUN:   | FileCheck --check-prefixes=ALL,NEW,N32,NEW-BE %s

diff  --git a/llvm/test/CodeGen/Mips/cconv/arguments.ll b/llvm/test/CodeGen/Mips/cconv/arguments.ll
index 75403ec8a4657..4621f8e66e49e 100644
--- a/llvm/test/CodeGen/Mips/cconv/arguments.ll
+++ b/llvm/test/CodeGen/Mips/cconv/arguments.ll
@@ -1,8 +1,8 @@
 ; RUN: llc -mtriple=mips -relocation-model=static < %s | FileCheck --check-prefixes=ALL,SYM32,O32 %s
 ; RUN: llc -mtriple=mipsel -relocation-model=static < %s | FileCheck --check-prefixes=ALL,SYM32,O32 %s
 
-; RUN-TODO: llc -mtriple=mips64 -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,SYM32,O32 %s
-; RUN-TODO: llc -mtriple=mips64el -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,SYM32,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64 -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,SYM32,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,SYM32,O32 %s
 
 ; RUN: llc -mtriple=mips64 -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,SYM32,NEW %s
 ; RUN: llc -mtriple=mips64el -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,SYM32,NEW %s

diff  --git a/llvm/test/CodeGen/Mips/cconv/callee-saved-float.ll b/llvm/test/CodeGen/Mips/cconv/callee-saved-float.ll
index 14d781dc57df8..07899b6b76a8e 100644
--- a/llvm/test/CodeGen/Mips/cconv/callee-saved-float.ll
+++ b/llvm/test/CodeGen/Mips/cconv/callee-saved-float.ll
@@ -3,10 +3,10 @@
 ; RUN: llc -mtriple=mips < %s | FileCheck --check-prefixes=ALL,O32-INV %s
 ; RUN: llc -mtriple=mipsel < %s | FileCheck --check-prefixes=ALL,O32-INV %s
 
-; RUN-TODO: llc -mtriple=mips64 -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
-; RUN-TODO: llc -mtriple=mips64el -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
-; RUN-TODO: llc -mtriple=mips64 -target-abi o32 < %s | FileCheck --check-prefixes=ALL,ALL-INV,O32-INV %s
-; RUN-TODO: llc -mtriple=mips64el -target-abi o32 < %s | FileCheck --check-prefixes=ALL,ALL-INV,O32-INV %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64 -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64 -target-abi o32 < %s | FileCheck --check-prefixes=ALL,ALL-INV,O32-INV %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el -target-abi o32 < %s | FileCheck --check-prefixes=ALL,ALL-INV,O32-INV %s
 
 ; RUN: llc -mtriple=mips64 -target-abi n32 < %s | FileCheck --check-prefixes=ALL,N32 %s
 ; RUN: llc -mtriple=mips64el -target-abi n32 < %s | FileCheck --check-prefixes=ALL,N32 %s

diff  --git a/llvm/test/CodeGen/Mips/cconv/callee-saved.ll b/llvm/test/CodeGen/Mips/cconv/callee-saved.ll
index 93808fbcad03d..c0223ae0c8c27 100644
--- a/llvm/test/CodeGen/Mips/cconv/callee-saved.ll
+++ b/llvm/test/CodeGen/Mips/cconv/callee-saved.ll
@@ -3,14 +3,14 @@
 ; RUN: llc -mtriple=mips   < %s | FileCheck --check-prefixes=ALL,O32-INV %s
 ; RUN: llc -mtriple=mipsel < %s | FileCheck --check-prefixes=ALL,O32-INV %s
 
-; RUN-TODO: llc -mtriple=mips64 -target-abi o32 < %s \
-; RUN-TODO:   | FileCheck --check-prefixes=ALL,O32 %s
-; RUN-TODO: llc -mtriple=mips64el -target-abi o32 < %s \
-; RUN-TODO:   | FileCheck --check-prefixes=ALL,O32 %s
-; RUN-TODO: llc -mtriple=mips64 -target-abi o32 < %s \
-; RUN-TODO:   | FileCheck --check-prefixes=ALL,O32-INV %s
-; RUN-TODO: llc -mtriple=mips64el -target-abi o32 < %s \
-; RUN-TODO:   | FileCheck --check-prefixes=ALL,O32-INV %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64 -target-abi o32 < %s \
+; RUN:   | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el -target-abi o32 < %s \
+; RUN:   | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64 -target-abi o32 < %s \
+; RUN:   | FileCheck --check-prefixes=ALL,O32-INV %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el -target-abi o32 < %s \
+; RUN:   | FileCheck --check-prefixes=ALL,O32-INV %s
 
 ; RUN: llc -mtriple=mips64 -target-abi n32 < %s \
 ; RUN:   | FileCheck --check-prefixes=ALL,N32 %s

diff  --git a/llvm/test/CodeGen/Mips/cconv/memory-layout.ll b/llvm/test/CodeGen/Mips/cconv/memory-layout.ll
index c95fe09de20e7..ceaaa832e6747 100644
--- a/llvm/test/CodeGen/Mips/cconv/memory-layout.ll
+++ b/llvm/test/CodeGen/Mips/cconv/memory-layout.ll
@@ -1,8 +1,8 @@
 ; RUN: llc -mtriple=mips-elf < %s | FileCheck --check-prefixes=ALL,O32 %s
 ; RUN: llc -mtriple=mipsel-elf < %s | FileCheck --check-prefixes=ALL,O32 %s
 
-; RUN-TODO: llc -mtriple=mips64-elf -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
-; RUN-TODO: llc -mtriple=mips64el-elf -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64-elf -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el-elf -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
 
 ; RUN: llc -mtriple=mips64-elf -target-abi n32 < %s | FileCheck --check-prefixes=ALL,N32 %s
 ; RUN: llc -mtriple=mips64el-elf -target-abi n32 < %s | FileCheck --check-prefixes=ALL,N32 %s

diff  --git a/llvm/test/CodeGen/Mips/cconv/o32-fp64-gpr-moves.ll b/llvm/test/CodeGen/Mips/cconv/o32-fp64-gpr-moves.ll
new file mode 100644
index 0000000000000..b6d7dde52852e
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/cconv/o32-fp64-gpr-moves.ll
@@ -0,0 +1,63 @@
+; RUN: llc -mtriple=mips64 -mcpu=mips3 -target-abi=o32 -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64el -mcpu=mips3 -target-abi=o32 -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64 -mcpu=mips4 -target-abi=o32 -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64el -mcpu=mips4 -target-abi=o32 -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64 -mcpu=mips64 -target-abi=o32 -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64el -mcpu=mips64 -target-abi=o32 -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64 -mcpu=mips64r2 -target-abi=o32 -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64el -mcpu=mips64r2 -target-abi=o32 -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64 -mcpu=mips64r6 -target-abi=o32 -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64el -mcpu=mips64r6 -target-abi=o32 -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64 -mcpu=mips64 -target-abi=o32 -mattr=+nooddspreg -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64el -mcpu=mips64 -target-abi=o32 -mattr=+nooddspreg -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64 -mcpu=mips64r2 -target-abi=o32 -mattr=+nooddspreg -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64el -mcpu=mips64r2 -target-abi=o32 -mattr=+nooddspreg -verify-machineinstrs -filetype=obj %s -o /dev/null
+; RUN: llc -mtriple=mips64 -mcpu=mips64 -target-abi=o32 -verify-machineinstrs < %s | FileCheck %s --check-prefix=SPILL
+; RUN: llc -mtriple=mips64el -mcpu=mips64 -target-abi=o32 -verify-machineinstrs < %s | FileCheck %s --check-prefix=SPILL
+; RUN: llc -mtriple=mips64 -mcpu=mips64r2 -target-abi=o32 -verify-machineinstrs < %s | FileCheck %s --check-prefix=DIRECT-BE
+; RUN: llc -mtriple=mips64el -mcpu=mips64r2 -target-abi=o32 -verify-machineinstrs < %s | FileCheck %s --check-prefix=DIRECT-LE
+
+; An integer argument before a double makes O32 pass that double in two
+; 32-bit GPRs. Check both directions of the transfer with 64-bit FPRs.
+; Before revision 2, MTHC1/MFHC1 are unavailable: the upper half of an FPR
+; cannot be accessed by applying MTC1/MFC1 to its sub_hi register.
+define double @from_gprs(i32 %pad, double %value) {
+; SPILL-LABEL: from_gprs:
+; SPILL:       addiu $sp, $sp, -8
+; SPILL:       sw $6, 0($sp)
+; SPILL-NEXT:  sw $7, 4($sp)
+; SPILL-NEXT:  ldc1 $f0, 0($sp)
+; SPILL:       addiu $sp, $sp, 8
+;
+; DIRECT-BE-LABEL: from_gprs:
+; DIRECT-BE:       mtc1 $7, $f0
+; DIRECT-BE-NEXT:  mthc1 $6, $f0
+;
+; DIRECT-LE-LABEL: from_gprs:
+; DIRECT-LE:       mtc1 $6, $f0
+; DIRECT-LE-NEXT:  mthc1 $7, $f0
+  ret double %value
+}
+
+declare void @consume(i32, double)
+
+define void @to_gprs(double %value) {
+; SPILL-LABEL: to_gprs:
+; SPILL:       sdc1 $f12, 16($sp)
+; SPILL-NEXT:  lw $6, 16($sp)
+; SPILL-NEXT:  sdc1 $f12, 16($sp)
+; SPILL-NEXT:  lw $7, 20($sp)
+; SPILL:       jal consume
+;
+; DIRECT-BE-LABEL: to_gprs:
+; DIRECT-BE-DAG:   mfhc1 $6, $f12
+; DIRECT-BE-DAG:   mfc1 $7, $f12
+; DIRECT-BE:       jal consume
+;
+; DIRECT-LE-LABEL: to_gprs:
+; DIRECT-LE-DAG:   mfc1 $6, $f12
+; DIRECT-LE-DAG:   mfhc1 $7, $f12
+; DIRECT-LE:       jal consume
+  call void @consume(i32 1, double %value)
+  ret void
+}

diff  --git a/llvm/test/CodeGen/Mips/cconv/o32-mips64.ll b/llvm/test/CodeGen/Mips/cconv/o32-mips64.ll
new file mode 100644
index 0000000000000..be4b0f914cc2e
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/cconv/o32-mips64.ll
@@ -0,0 +1,124 @@
+; RUN: llc -mtriple=mips64 -target-abi=o32 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=BE,HARD
+; RUN: llc -mtriple=mips64el -target-abi=o32 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=LE,HARD
+; RUN: llc -mtriple=mips64 -target-abi=o32 -mattr=+soft-float -verify-machineinstrs < %s | FileCheck %s --check-prefixes=BE,SOFT-BE
+; RUN: llc -mtriple=mips64el -target-abi=o32 -mattr=+soft-float -verify-machineinstrs < %s | FileCheck %s --check-prefixes=LE,SOFT-LE
+; RUN: llc -mtriple=mips64 -mcpu=mips64r2 -target-abi=o32 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=ALL,O32-BE
+; RUN: llc -mtriple=mips64el -mcpu=mips64r2 -target-abi=o32 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=ALL,O32-LE
+; RUN: llc -mtriple=mips64 -mcpu=mips64r2 -target-abi=n32 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=ALL,NABI
+; RUN: llc -mtriple=mips64el -mcpu=mips64r2 -target-abi=n32 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=ALL,NABI
+; RUN: llc -mtriple=mips64 -mcpu=mips64r2 -target-abi=n64 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=ALL,NABI
+; RUN: llc -mtriple=mips64el -mcpu=mips64r2 -target-abi=n64 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=ALL,NABI
+
+; Selecting O32's GPR mode must preserve the CPU's revision 2 instructions
+; and 64-bit FPR mode. N32/N64 must continue to use 64-bit GPR operations.
+; O32-BE: .module fp=64
+; O32-LE: .module fp=64
+
+declare i32 @llvm.fshr.i32(i32, i32, i32)
+
+define i32 @rotate(i32 %value) {
+; ALL-LABEL: rotate:
+; O32-BE: rotr $2, $4, 7
+; O32-LE: rotr $2, $4, 7
+; NABI: sll [[WORD:\$[0-9]+]], $4, 0
+; NABI: rotr $2, [[WORD]], 7
+  %result = call i32 @llvm.fshr.i32(i32 %value, i32 %value, i32 7)
+  ret i32 %result
+}
+
+define double @add_double(double %x, double %y) {
+; ALL-LABEL: add_double:
+; O32-BE: add.d $f0, $f12, $f14
+; O32-LE: add.d $f0, $f12, $f14
+; NABI: add.d $f0, $f12, $f13
+  %result = fadd double %x, %y
+  ret double %result
+}
+
+define i64 @increment(i64 %value) {
+; ALL-LABEL: increment:
+; O32-BE: addiu $3, $5, 1
+; O32-BE: sltiu $1, $3, 1
+; O32-BE: addu $2, $4, $1
+; O32-LE: addiu $2, $4, 1
+; O32-LE: sltiu $1, $2, 1
+; O32-LE: addu $3, $5, $1
+; NABI: daddiu $2, $4, 1
+  %result = add i64 %value, 1
+  ret i64 %result
+}
+
+; O32 passes and returns i64 in pairs of 32-bit registers even on a 64-bit
+; CPU. The caller and callee must agree on the pieces.
+define i64 @identity_i64(i64 %value) {
+; BE-LABEL: identity_i64:
+; BE:       # %bb.0:
+; BE-NEXT:    move $2, $4
+; BE-NEXT:    jr $ra
+; BE-NEXT:    move $3, $5
+;
+; LE-LABEL: identity_i64:
+; LE:       # %bb.0:
+; LE-NEXT:    move $2, $4
+; LE-NEXT:    jr $ra
+; LE-NEXT:    move $3, $5
+  ret i64 %value
+}
+
+declare i64 @get_i64()
+
+define i64 @call_i64() {
+; BE-LABEL: call_i64:
+; BE:       # %bb.0:
+; BE-NEXT:    addiu $sp, $sp, -24
+; BE-NEXT:    .cfi_def_cfa_offset 24
+; BE-NEXT:    sw $ra, 20($sp) # 4-byte Folded Spill
+; BE-NEXT:    .cfi_offset 31, -4
+; BE-NEXT:    jal get_i64
+; BE-NEXT:    nop
+; BE-NEXT:    addiu $3, $3, 1
+; BE-NEXT:    sltiu $1, $3, 1
+; BE-NEXT:    addu $2, $2, $1
+; BE-NEXT:    lw $ra, 20($sp) # 4-byte Folded Reload
+; BE-NEXT:    jr $ra
+; BE-NEXT:    addiu $sp, $sp, 24
+;
+; LE-LABEL: call_i64:
+; LE:       # %bb.0:
+; LE-NEXT:    addiu $sp, $sp, -24
+; LE-NEXT:    .cfi_def_cfa_offset 24
+; LE-NEXT:    sw $ra, 20($sp) # 4-byte Folded Spill
+; LE-NEXT:    .cfi_offset 31, -4
+; LE-NEXT:    jal get_i64
+; LE-NEXT:    nop
+; LE-NEXT:    addiu $2, $2, 1
+; LE-NEXT:    sltiu $1, $2, 1
+; LE-NEXT:    addu $3, $3, $1
+; LE-NEXT:    lw $ra, 20($sp) # 4-byte Folded Reload
+; LE-NEXT:    jr $ra
+; LE-NEXT:    addiu $sp, $sp, 24
+  %value = call i64 @get_i64()
+  %result = add i64 %value, 1
+  ret i64 %result
+}
+
+; Soft-float doubles use the same integer register pairs.
+define double @identity_double(double %value) {
+; HARD-LABEL: identity_double:
+; HARD:       # %bb.0:
+; HARD-NEXT:    jr $ra
+; HARD-NEXT:    mov.d $f0, $f12
+;
+; SOFT-BE-LABEL: identity_double:
+; SOFT-BE:       # %bb.0:
+; SOFT-BE-NEXT:    move $2, $4
+; SOFT-BE-NEXT:    jr $ra
+; SOFT-BE-NEXT:    move $3, $5
+;
+; SOFT-LE-LABEL: identity_double:
+; SOFT-LE:       # %bb.0:
+; SOFT-LE-NEXT:    move $2, $4
+; SOFT-LE-NEXT:    jr $ra
+; SOFT-LE-NEXT:    move $3, $5
+  ret double %value
+}

diff  --git a/llvm/test/CodeGen/Mips/cconv/reserved-space.ll b/llvm/test/CodeGen/Mips/cconv/reserved-space.ll
index 490476961626e..b86ba808f11f9 100644
--- a/llvm/test/CodeGen/Mips/cconv/reserved-space.ll
+++ b/llvm/test/CodeGen/Mips/cconv/reserved-space.ll
@@ -1,8 +1,8 @@
 ; RUN: llc -mtriple=mips < %s | FileCheck --check-prefixes=ALL,O32 %s
 ; RUN: llc -mtriple=mipsel < %s | FileCheck --check-prefixes=ALL,O32 %s
 
-; RUN-TODO: llc -mtriple=mips64 -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
-; RUN-TODO: llc -mtriple=mips64el -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64 -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
 
 ; RUN: llc -mtriple=mips64 -target-abi n32 < %s | FileCheck --check-prefixes=ALL,N32 %s
 ; RUN: llc -mtriple=mips64el -target-abi n32 < %s | FileCheck --check-prefixes=ALL,N32 %s

diff  --git a/llvm/test/CodeGen/Mips/cconv/return-float.ll b/llvm/test/CodeGen/Mips/cconv/return-float.ll
index 8b9be38179acf..3fe583546ec26 100644
--- a/llvm/test/CodeGen/Mips/cconv/return-float.ll
+++ b/llvm/test/CodeGen/Mips/cconv/return-float.ll
@@ -1,8 +1,8 @@
 ; RUN: llc -mtriple=mips-linux-gnu -mattr=+soft-float -relocation-model=static < %s | FileCheck --check-prefixes=ALL,O32 %s
 ; RUN: llc -mtriple=mipsel-linux-gnu -mattr=+soft-float -relocation-model=static < %s | FileCheck --check-prefixes=ALL,O32 %s
 
-; RUN-TODO: llc -mtriple=mips64-linux-gnu -mattr=+soft-float -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
-; RUN-TODO: llc -mtriple=mips64el-linux-gnu -mattr=+soft-float -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64-linux-gnu -mattr=+soft-float -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el-linux-gnu -mattr=+soft-float -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
 
 ; RUN: llc -mtriple=mips64-linux-gnu -mattr=+soft-float -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,N32 %s
 ; RUN: llc -mtriple=mips64el-linux-gnu -mattr=+soft-float -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,N32 %s

diff  --git a/llvm/test/CodeGen/Mips/cconv/return-hard-float.ll b/llvm/test/CodeGen/Mips/cconv/return-hard-float.ll
index 5f2aeee09f398..0043faff2dfc1 100644
--- a/llvm/test/CodeGen/Mips/cconv/return-hard-float.ll
+++ b/llvm/test/CodeGen/Mips/cconv/return-hard-float.ll
@@ -3,10 +3,10 @@
 ; RUN: llc -mtriple=mipsel-linux-gnu -relocation-model=static < %s \
 ; RUN:   | FileCheck --check-prefixes=ALL,O32 %s
 
-; RUN-TODO: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi o32 < %s \
-; RUN-TODO:   | FileCheck --check-prefixes=ALL,O32 %s
-; RUN-TODO: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi o32 < %s \
-; RUN-TODO:   | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64-linux-gnu -relocation-model=static -target-abi o32 < %s \
+; RUN:   | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi o32 < %s \
+; RUN:   | FileCheck --check-prefixes=ALL,O32 %s
 
 ; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi n32 < %s \
 ; RUN:   | FileCheck --check-prefixes=ALL,N32 %s

diff  --git a/llvm/test/CodeGen/Mips/cconv/return-struct.ll b/llvm/test/CodeGen/Mips/cconv/return-struct.ll
index 68f8127ae9f13..109e160161f54 100644
--- a/llvm/test/CodeGen/Mips/cconv/return-struct.ll
+++ b/llvm/test/CodeGen/Mips/cconv/return-struct.ll
@@ -4,10 +4,10 @@
 ; RUN: llc -mtriple=mipsel-linux-gnu -relocation-model=static < %s \
 ; RUN:   | FileCheck --check-prefixes=O32,O32-LE %s
 
-; RUN-TODO: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi o32 < %s \
-; RUN-TODO:   | FileCheck --check-prefixes=O32 %s
-; RUN-TODO: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi o32 < %s \
-; RUN-TODO:   | FileCheck --check-prefixes=O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64-linux-gnu -relocation-model=static -target-abi o32 < %s \
+; RUN:   | FileCheck --check-prefixes=O32,O32-BE %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi o32 < %s \
+; RUN:   | FileCheck --check-prefixes=O32,O32-LE %s
 
 ; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi n32 < %s \
 ; RUN:   | FileCheck --check-prefixes=N32,N32-BE %s

diff  --git a/llvm/test/CodeGen/Mips/cconv/return.ll b/llvm/test/CodeGen/Mips/cconv/return.ll
index f0e4545bd4559..c9fc8de3a96fe 100644
--- a/llvm/test/CodeGen/Mips/cconv/return.ll
+++ b/llvm/test/CodeGen/Mips/cconv/return.ll
@@ -1,8 +1,8 @@
 ; RUN: llc -mtriple=mips-linux-gnu -relocation-model=static < %s | FileCheck --check-prefixes=ALL,O32 %s
 ; RUN: llc -mtriple=mipsel-linux-gnu -relocation-model=static < %s | FileCheck --check-prefixes=ALL,O32 %s
 
-; RUN-TODO: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
-; RUN-TODO: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi o32 -verify-machineinstrs < %s | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi o32 -verify-machineinstrs < %s | FileCheck --check-prefixes=ALL,O32 %s
 
 ; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,N32 %s
 ; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,N32 %s

diff  --git a/llvm/test/CodeGen/Mips/cconv/stack-alignment.ll b/llvm/test/CodeGen/Mips/cconv/stack-alignment.ll
index 9cdb8428b484a..9e93f0396e397 100644
--- a/llvm/test/CodeGen/Mips/cconv/stack-alignment.ll
+++ b/llvm/test/CodeGen/Mips/cconv/stack-alignment.ll
@@ -1,8 +1,8 @@
 ; RUN: llc -mtriple=mips < %s | FileCheck --check-prefixes=ALL,O32 %s
 ; RUN: llc -mtriple=mipsel < %s | FileCheck --check-prefixes=ALL,O32 %s
 
-; RUN-TODO: llc -mtriple=mips64 -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
-; RUN-TODO: llc -mtriple=mips64el -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64 -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
+; RUN: llc -verify-machineinstrs -mtriple=mips64el -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s
 
 ; RUN: llc -mtriple=mips64 -target-abi n32 < %s | FileCheck --check-prefixes=ALL,N32 %s
 ; RUN: llc -mtriple=mips64el -target-abi n32 < %s | FileCheck --check-prefixes=ALL,N32 %s


        


More information about the llvm-commits mailing list