[mips] Prevent shrink-wrap for BuildPairF64, ExtractElementF64 when they use $sp
For a certain combination of options, BuildPairF64_{64}, ExtractElementF64{_64}
may be expanded into instructions using stack.
Add implicit operand $sp for such cases so that ShrinkWrapping doesn't move
prologue setup below them.
Fixes MultiSource/Benchmarks/MallocBench/cfrac for
'--target=mips-img-linux-gnu -mcpu=mips32r6 -mfpxx -mnan=2008'
and
'--target=mips-img-linux-gnu -mcpu=mips32r6 -mfp64 -mnan=2008 -mno-odd-spreg'.
Differential Revision: https://reviews.llvm.org/D50986
llvm-svn: 340927
diff --git a/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp b/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
index 687c9f6..ef1b3c0 100644
--- a/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
@@ -299,8 +299,12 @@
   // register). Unfortunately, we have to make this decision before register
   // allocation so for now we use a spill/reload sequence for all
   // double-precision values in regardless of being an odd/even register.
-  if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) ||
-      (FP64 && !Subtarget.useOddSPReg())) {
+  //
+  // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as
+  // implicit operand, so other passes (like ShrinkWrapping) are aware that
+  // stack is used.
+  if (I->getNumOperands() == 4 && I->getOperand(3).isReg()
+      && I->getOperand(3).getReg() == Mips::SP) {
     unsigned DstReg = I->getOperand(0).getReg();
     unsigned LoReg = I->getOperand(1).getReg();
     unsigned HiReg = I->getOperand(2).getReg();
@@ -360,9 +364,12 @@
   // register). Unfortunately, we have to make this decision before register
   // allocation so for now we use a spill/reload sequence for all
   // double-precision values in regardless of being an odd/even register.
-
-  if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) ||
-      (FP64 && !Subtarget.useOddSPReg())) {
+  //
+  // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as
+  // implicit operand, so other passes (like ShrinkWrapping) are aware that
+  // stack is used.
+  if (I->getNumOperands() == 4 && I->getOperand(3).isReg()
+      && I->getOperand(3).getReg() == Mips::SP) {
     unsigned DstReg = I->getOperand(0).getReg();
     unsigned SrcReg = Op1.getReg();
     unsigned N = Op2.getImm();
diff --git a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
index 599c1e9..cf2899d 100644
--- a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
@@ -238,6 +238,18 @@
       case Mips::WRDSP:
         addDSPCtrlRegOperands(true, MI, MF);
         break;
+      case Mips::BuildPairF64_64:
+      case Mips::ExtractElementF64_64:
+        if (!Subtarget->useOddSPReg()) {
+          MI.addOperand(MachineOperand::CreateReg(Mips::SP, false, true));
+          break;
+        }
+      // fallthrough
+      case Mips::BuildPairF64:
+      case Mips::ExtractElementF64:
+        if (Subtarget->isABI_FPXX() && !Subtarget->hasMTHC1())
+          MI.addOperand(MachineOperand::CreateReg(Mips::SP, false, true));
+        break;
       default:
         replaceUsesWithZeroReg(MRI, MI);
       }