[llvm-commits] MIPS patch

Akira Hatanaka ahatanak at gmail.com
Thu Apr 7 18:01:58 PDT 2011


This patch defines two pseudo instructions that are expanded to a pair of
mtc1 or mtf1 instructions after register allocation.

Previously, f64 arguments passed in integer registers were read and written
via load and store instructions (2 i32 stores and 1 f64 load were needed
when reading a double value and 1 f64 store and 2 i32 loads were needed when
writing one). After applying this patch, mtc1 or mfc1 instructions are
generated instead which are register transfer instructions between integer
and floating point register files.

Index: test/CodeGen/Mips/buildpairextractelementf64.ll
===================================================================
--- test/CodeGen/Mips/buildpairextractelementf64.ll    (revision 0)
+++ test/CodeGen/Mips/buildpairextractelementf64.ll    (revision 0)
@@ -0,0 +1,27 @@
+; RUN: llc  < %s -march=mipsel | FileCheck %s -check-prefix=CHECK-EL
+; RUN: llc  < %s -march=mips   | FileCheck %s -check-prefix=CHECK-EB
+ at a = external global i32
+
+define double @f(i32 %a1, double %d) nounwind {
+entry:
+; CHECK-EL: mtc1 $6, $f12
+; CHECK-EL: mtc1 $7, $f13
+; CHECK-EB: mtc1 $7, $f12
+; CHECK-EB: mtc1 $6, $f13
+  store i32 %a1, i32* @a, align 4
+  %add = fadd double %d, 2.000000e+00
+  ret double %add
+}
+
+define void @f3(double %d, i32 %a1) nounwind {
+entry:
+; CHECK-EL: mfc1 ${{[0-9]+}}, $f12
+; CHECK-EL: mfc1 $7, $f13
+; CHECK-EB: mfc1 ${{[0-9]+}}, $f13
+; CHECK-EB: mfc1 $7, $f12
+  tail call void @f2(i32 %a1, double %d) nounwind
+  ret void
+}
+
+declare void @f2(i32, double)
+
Index: lib/Target/Mips/MipsTargetMachine.cpp
===================================================================
--- lib/Target/Mips/MipsTargetMachine.cpp    (revision 129116)
+++ lib/Target/Mips/MipsTargetMachine.cpp    (working copy)
@@ -75,3 +75,9 @@
   PM.add(createMipsDelaySlotFillerPass(*this));
   return true;
 }
+
+bool MipsTargetMachine::
+addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) {
+  PM.add(createMipsExpandPseudoInstrsPass(*this));
+  return true;
+}
Index: lib/Target/Mips/Mips.h
===================================================================
--- lib/Target/Mips/Mips.h    (revision 129116)
+++ lib/Target/Mips/Mips.h    (working copy)
@@ -25,7 +25,7 @@

   FunctionPass *createMipsISelDag(MipsTargetMachine &TM);
   FunctionPass *createMipsDelaySlotFillerPass(MipsTargetMachine &TM);
-
+  FunctionPass *createMipsExpandPseudoInstrsPass(MipsTargetMachine &TM);
   extern Target TheMipsTarget;
   extern Target TheMipselTarget;

Index: lib/Target/Mips/MipsISelLowering.h
===================================================================
--- lib/Target/Mips/MipsISelLowering.h    (revision 129116)
+++ lib/Target/Mips/MipsISelLowering.h    (working copy)
@@ -64,7 +64,10 @@

       // DivRem(u)
       DivRem,
-      DivRemU
+      DivRemU,
+
+      BuildPairF64,
+      ExtractElementF64
     };
   }

Index: lib/Target/Mips/MipsTargetMachine.h
===================================================================
--- lib/Target/Mips/MipsTargetMachine.h    (revision 129116)
+++ lib/Target/Mips/MipsTargetMachine.h    (working copy)
@@ -63,6 +63,7 @@
                                  CodeGenOpt::Level OptLevel);
     virtual bool addPreEmitPass(PassManagerBase &PM,
                                 CodeGenOpt::Level OptLevel);
+    virtual bool addPostRegAlloc(PassManagerBase &, CodeGenOpt::Level);
   };

 /// MipselTargetMachine - Mipsel target machine.
Index: lib/Target/Mips/MipsInstrFPU.td
===================================================================
--- lib/Target/Mips/MipsInstrFPU.td    (revision 129116)
+++ lib/Target/Mips/MipsInstrFPU.td    (working copy)
@@ -30,6 +30,12 @@
                                          SDTCisInt<2>]>;
 def SDT_MipsCMovFP : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
                                           SDTCisSameAs<1, 2>]>;
+def SDT_MipsBuildPairF64 : SDTypeProfile<1, 2, [SDTCisVT<0, f64>,
+                                                SDTCisVT<1, i32>,
+                                                SDTCisSameAs<1, 2>]>;
+def SDT_MipsExtractElementF64 : SDTypeProfile<1, 2, [SDTCisVT<0, i32>,
+                                                     SDTCisVT<1, f64>,
+                                                     SDTCisVT<0, i32>]>;

 def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp, [SDNPOutGlue]>;
 def MipsCMovFP_T : SDNode<"MipsISD::CMovFP_T", SDT_MipsCMovFP,
[SDNPInGlue]>;
@@ -37,6 +43,9 @@
 def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp,
[SDNPOptInGlue]>;
 def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond,
                           [SDNPHasChain, SDNPOptInGlue]>;
+def MipsBuildPairF64 : SDNode<"MipsISD::BuildPairF64",
SDT_MipsBuildPairF64>;
+def MipsExtractElementF64 : SDNode<"MipsISD::ExtractElementF64",
+                                   SDT_MipsExtractElementF64>;

 // Operand for printing out a condition code.
 let PrintMethod = "printFCCOperand" in
@@ -312,6 +321,21 @@
 def MOVCCRToCCR : MipsPseudo<(outs CCR:$dst), (ins CCR:$src),
                              "# MOVCCRToCCR", []>;

+// This pseudo instr gets expanded to 2 mtc1 instrs after register
allocation.
+def BuildPairF64 :
+  MipsPseudo<(outs AFGR64:$dst),
+             (ins CPURegs:$lo, CPURegs:$hi), "buildpair64\t$dst, $lo, $hi",
+             [(set AFGR64:$dst, (MipsBuildPairF64 CPURegs:$lo,
CPURegs:$hi))]>;
+
+// This pseudo instr gets expanded to 2 mfc1 instrs after register
allocation.
+// if n is 0, lower part of src is extracted.
+// if n is 1, higher part of src is extracted.
+def hiorlo : Operand<i32>;
+def ExtractElementF64 :
+  MipsPseudo<(outs CPURegs:$dst),
+             (ins AFGR64:$src, hiorlo:$n), "extractelement64\t$dst, $src,
$n",
+             [(set CPURegs:$dst, (MipsExtractElementF64 AFGR64:$src,
imm:$n))]>;
+
 //===----------------------------------------------------------------------===//
 // Floating Point Patterns
 //===----------------------------------------------------------------------===//
Index: lib/Target/Mips/MipsExpandPseudoInstrs.cpp
===================================================================
--- lib/Target/Mips/MipsExpandPseudoInstrs.cpp    (revision 0)
+++ lib/Target/Mips/MipsExpandPseudoInstrs.cpp    (revision 0)
@@ -0,0 +1,116 @@
+//===-- ExpandPseudoInstrs.cpp - Mips delay slot filler
---------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Pass run after register allocation that expands pseudo
+// instructions to a pair of mtc1 or mfc1 instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "expand-pseudo-instrs"
+
+#include "Mips.h"
+#include "MipsTargetMachine.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/ADT/Statistic.h"
+
+using namespace llvm;
+
+namespace {
+  struct ExpandPseudoInstrs : public MachineFunctionPass {
+
+    TargetMachine &TM;
+    const TargetInstrInfo *TII;
+
+    static char ID;
+    ExpandPseudoInstrs(TargetMachine &tm)
+      : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { }
+
+    virtual const char *getPassName() const {
+      return "Mips PseudoInstrs Expansion";
+    }
+
+    bool runOnMachineFunction(MachineFunction &F);
+    bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
+
+  private:
+    void ExpandBuildPairF64(MachineBasicBlock&,
MachineBasicBlock::iterator);
+    void ExpandExtractElementF64(MachineBasicBlock&,
MachineBasicBlock::iterator);
+  };
+  char ExpandPseudoInstrs::ID = 0;
+} // end of anonymous namespace
+
+bool ExpandPseudoInstrs::runOnMachineFunction(MachineFunction& F) {
+  bool Changed = false;
+
+  for (MachineFunction::iterator I = F.begin(); I != F.end(); ++I)
+    Changed |= runOnMachineBasicBlock(*I);
+
+  return Changed;
+}
+
+bool ExpandPseudoInstrs::runOnMachineBasicBlock(MachineBasicBlock& MBB) {
+
+  bool Changed = false;
+  for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) {
+    const TargetInstrDesc& Tid = I->getDesc();
+
+    switch(Tid.getOpcode()) {
+    default:
+      ++I;
+      continue;
+    case Mips::BuildPairF64:
+      ExpandBuildPairF64(MBB, I);
+      break;
+    case Mips::ExtractElementF64:
+      ExpandExtractElementF64(MBB, I);
+      break;
+    }
+
+    // delete original instr
+    MBB.erase(I++);
+    Changed = true;
+  }
+
+  return Changed;
+}
+
+void ExpandPseudoInstrs::ExpandBuildPairF64(MachineBasicBlock& MBB,
+                                            MachineBasicBlock::iterator I)
{
+  unsigned DstReg = I->getOperand(0).getReg();
+  unsigned LoReg = I->getOperand(1).getReg(), HiReg =
I->getOperand(2).getReg();
+  const TargetInstrDesc& Mtc1Tdd = TII->get(Mips::MTC1);
+  DebugLoc dl = I->getDebugLoc();
+  const unsigned* SubReg =
+    TM.getRegisterInfo()->getSubRegisters(DstReg);
+
+  // mtc1 Lo, $fp
+  // mtc1 Hi, $fp + 1
+  BuildMI(MBB, I, dl, Mtc1Tdd, *SubReg).addReg(LoReg);
+  BuildMI(MBB, I, dl, Mtc1Tdd, *(SubReg + 1)).addReg(HiReg);
+}
+
+void ExpandPseudoInstrs::ExpandExtractElementF64(MachineBasicBlock& MBB,
+
MachineBasicBlock::iterator I) {
+  unsigned DstReg = I->getOperand(0).getReg();
+  unsigned SrcReg = I->getOperand(1).getReg();
+  unsigned N = I->getOperand(2).getImm();
+  const TargetInstrDesc& Mfc1Tdd = TII->get(Mips::MFC1);
+  DebugLoc dl = I->getDebugLoc();
+  const unsigned* SubReg = TM.getRegisterInfo()->getSubRegisters(SrcReg);
+
+  BuildMI(MBB, I, dl, Mfc1Tdd, DstReg).addReg(*(SubReg + N));
+}
+
+/// createMipsExpandPseudoInstrsPass - Returns a pass that expands pseudo
+/// instrs into real instrs
+FunctionPass *llvm::createMipsExpandPseudoInstrsPass(MipsTargetMachine &tm)
{
+  return new ExpandPseudoInstrs(tm);
+}
Index: lib/Target/Mips/MipsISelLowering.cpp
===================================================================
--- lib/Target/Mips/MipsISelLowering.cpp    (revision 129116)
+++ lib/Target/Mips/MipsISelLowering.cpp    (working copy)
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//

 #define DEBUG_TYPE "mips-lower"
+#include <algorithm>
 #include "MipsISelLowering.h"
 #include "MipsMachineFunction.h"
 #include "MipsTargetMachine.h"
@@ -52,6 +53,8 @@
     case MipsISD::MSubu      : return "MipsISD::MSubu";
     case MipsISD::DivRem     : return "MipsISD::DivRem";
     case MipsISD::DivRemU    : return "MipsISD::DivRemU";
+    case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64";
+    case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64";
     default                  : return NULL;
   }
 }
@@ -1132,11 +1135,12 @@
         if (VA.getValVT() == MVT::f32 && VA.getLocVT() == MVT::i32)
           Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg);
         if (VA.getValVT() == MVT::f64 && VA.getLocVT() == MVT::i32) {
-          Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i64, Arg);
-          SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Arg,
-                                   DAG.getConstant(0, getPointerTy()));
-          SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Arg,
-                                   DAG.getConstant(1, getPointerTy()));
+          SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, dl,
MVT::i32, Arg,
+                                   DAG.getConstant(0, MVT::i32));
+          SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, dl,
MVT::i32, Arg,
+                                   DAG.getConstant(1, MVT::i32));
+          if (!Subtarget->isLittle())
+            std::swap(Lo, Hi);
           RegsToPass.push_back(std::make_pair(VA.getLocReg(), Lo));
           RegsToPass.push_back(std::make_pair(VA.getLocReg()+1, Hi));
           continue;
@@ -1429,9 +1433,10 @@
           unsigned Reg2 = AddLiveIn(DAG.getMachineFunction(),
                                     VA.getLocReg()+1, RC);
           SDValue ArgValue2 = DAG.getCopyFromReg(Chain, dl, Reg2, RegVT);
-          SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64,
ArgValue,
-                                       ArgValue2);
-          ArgValue = DAG.getNode(ISD::BITCAST, dl, MVT::f64, Pair);
+          if (!Subtarget->isLittle())
+            std::swap(ArgValue, ArgValue2);
+          ArgValue = DAG.getNode(MipsISD::BuildPairF64, dl, MVT::f64,
+                                 ArgValue, ArgValue2);
         }
       }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20110407/e6b6a858/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: buildpairexpandf64.patch
Type: text/x-patch
Size: 12109 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20110407/e6b6a858/attachment.bin>


More information about the llvm-commits mailing list