Home | History | Annotate | Download | only in Mips
      1 //===-- MipsSERegisterInfo.cpp - MIPS32/64 Register Information -== -------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains the MIPS32/64 implementation of the TargetRegisterInfo
     11 // class.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "MipsSERegisterInfo.h"
     16 #include "Mips.h"
     17 #include "MipsMachineFunction.h"
     18 #include "MipsSEInstrInfo.h"
     19 #include "MipsSubtarget.h"
     20 #include "MipsTargetMachine.h"
     21 #include "llvm/ADT/STLExtras.h"
     22 #include "llvm/CodeGen/MachineFrameInfo.h"
     23 #include "llvm/CodeGen/MachineFunction.h"
     24 #include "llvm/CodeGen/MachineInstrBuilder.h"
     25 #include "llvm/CodeGen/MachineRegisterInfo.h"
     26 #include "llvm/CodeGen/TargetFrameLowering.h"
     27 #include "llvm/CodeGen/TargetInstrInfo.h"
     28 #include "llvm/IR/Constants.h"
     29 #include "llvm/IR/DebugInfo.h"
     30 #include "llvm/IR/Function.h"
     31 #include "llvm/IR/Type.h"
     32 #include "llvm/Support/Debug.h"
     33 #include "llvm/Support/ErrorHandling.h"
     34 #include "llvm/Support/raw_ostream.h"
     35 #include "llvm/Target/TargetMachine.h"
     36 #include "llvm/Target/TargetOptions.h"
     37 
     38 using namespace llvm;
     39 
     40 #define DEBUG_TYPE "mips-reg-info"
     41 
     42 MipsSERegisterInfo::MipsSERegisterInfo() : MipsRegisterInfo() {}
     43 
     44 bool MipsSERegisterInfo::
     45 requiresRegisterScavenging(const MachineFunction &MF) const {
     46   return true;
     47 }
     48 
     49 bool MipsSERegisterInfo::
     50 requiresFrameIndexScavenging(const MachineFunction &MF) const {
     51   return true;
     52 }
     53 
     54 const TargetRegisterClass *
     55 MipsSERegisterInfo::intRegClass(unsigned Size) const {
     56   if (Size == 4)
     57     return &Mips::GPR32RegClass;
     58 
     59   assert(Size == 8);
     60   return &Mips::GPR64RegClass;
     61 }
     62 
     63 /// Get the size of the offset supported by the given load/store/inline asm.
     64 /// The result includes the effects of any scale factors applied to the
     65 /// instruction immediate.
     66 static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode,
     67                                                     MachineOperand MO) {
     68   switch (Opcode) {
     69   case Mips::LD_B:
     70   case Mips::ST_B:
     71     return 10;
     72   case Mips::LD_H:
     73   case Mips::ST_H:
     74     return 10 + 1 /* scale factor */;
     75   case Mips::LD_W:
     76   case Mips::ST_W:
     77     return 10 + 2 /* scale factor */;
     78   case Mips::LD_D:
     79   case Mips::ST_D:
     80     return 10 + 3 /* scale factor */;
     81   case Mips::LL:
     82   case Mips::LL64:
     83   case Mips::LLD:
     84   case Mips::LLE:
     85   case Mips::SC:
     86   case Mips::SC64:
     87   case Mips::SCD:
     88   case Mips::SCE:
     89     return 16;
     90   case Mips::LLE_MM:
     91   case Mips::LL_MM:
     92   case Mips::SCE_MM:
     93   case Mips::SC_MM:
     94     return 12;
     95   case Mips::LL64_R6:
     96   case Mips::LL_R6:
     97   case Mips::LLD_R6:
     98   case Mips::SC64_R6:
     99   case Mips::SCD_R6:
    100   case Mips::SC_R6:
    101   case Mips::LL_MMR6:
    102   case Mips::SC_MMR6:
    103     return 9;
    104   case Mips::INLINEASM: {
    105     unsigned ConstraintID = InlineAsm::getMemoryConstraintID(MO.getImm());
    106     switch (ConstraintID) {
    107     case InlineAsm::Constraint_ZC: {
    108       const MipsSubtarget &Subtarget = MO.getParent()
    109                                            ->getParent()
    110                                            ->getParent()
    111                                            ->getSubtarget<MipsSubtarget>();
    112       if (Subtarget.inMicroMipsMode())
    113         return 12;
    114 
    115       if (Subtarget.hasMips32r6())
    116         return 9;
    117 
    118       return 16;
    119     }
    120     default:
    121       return 16;
    122     }
    123   }
    124   default:
    125     return 16;
    126   }
    127 }
    128 
    129 /// Get the scale factor applied to the immediate in the given load/store.
    130 static inline unsigned getLoadStoreOffsetAlign(const unsigned Opcode) {
    131   switch (Opcode) {
    132   case Mips::LD_H:
    133   case Mips::ST_H:
    134     return 2;
    135   case Mips::LD_W:
    136   case Mips::ST_W:
    137     return 4;
    138   case Mips::LD_D:
    139   case Mips::ST_D:
    140     return 8;
    141   default:
    142     return 1;
    143   }
    144 }
    145 
    146 void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
    147                                      unsigned OpNo, int FrameIndex,
    148                                      uint64_t StackSize,
    149                                      int64_t SPOffset) const {
    150   MachineInstr &MI = *II;
    151   MachineFunction &MF = *MI.getParent()->getParent();
    152   MachineFrameInfo &MFI = MF.getFrameInfo();
    153   MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
    154 
    155   MipsABIInfo ABI =
    156       static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI();
    157   const MipsRegisterInfo *RegInfo =
    158     static_cast<const MipsRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
    159 
    160   const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
    161   int MinCSFI = 0;
    162   int MaxCSFI = -1;
    163 
    164   if (CSI.size()) {
    165     MinCSFI = CSI[0].getFrameIdx();
    166     MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
    167   }
    168 
    169   bool EhDataRegFI = MipsFI->isEhDataRegFI(FrameIndex);
    170   bool IsISRRegFI = MipsFI->isISRRegFI(FrameIndex);
    171   // The following stack frame objects are always referenced relative to $sp:
    172   //  1. Outgoing arguments.
    173   //  2. Pointer to dynamically allocated stack space.
    174   //  3. Locations for callee-saved registers.
    175   //  4. Locations for eh data registers.
    176   //  5. Locations for ISR saved Coprocessor 0 registers 12 & 14.
    177   // Everything else is referenced relative to whatever register
    178   // getFrameRegister() returns.
    179   unsigned FrameReg;
    180 
    181   if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) || EhDataRegFI ||
    182       IsISRRegFI)
    183     FrameReg = ABI.GetStackPtr();
    184   else if (RegInfo->needsStackRealignment(MF)) {
    185     if (MFI.hasVarSizedObjects() && !MFI.isFixedObjectIndex(FrameIndex))
    186       FrameReg = ABI.GetBasePtr();
    187     else if (MFI.isFixedObjectIndex(FrameIndex))
    188       FrameReg = getFrameRegister(MF);
    189     else
    190       FrameReg = ABI.GetStackPtr();
    191   } else
    192     FrameReg = getFrameRegister(MF);
    193 
    194   // Calculate final offset.
    195   // - There is no need to change the offset if the frame object is one of the
    196   //   following: an outgoing argument, pointer to a dynamically allocated
    197   //   stack space or a $gp restore location,
    198   // - If the frame object is any of the following, its offset must be adjusted
    199   //   by adding the size of the stack:
    200   //   incoming argument, callee-saved register location or local variable.
    201   bool IsKill = false;
    202   int64_t Offset;
    203 
    204   Offset = SPOffset + (int64_t)StackSize;
    205   Offset += MI.getOperand(OpNo + 1).getImm();
    206 
    207   LLVM_DEBUG(errs() << "Offset     : " << Offset << "\n"
    208                     << "<--------->\n");
    209 
    210   if (!MI.isDebugValue()) {
    211     // Make sure Offset fits within the field available.
    212     // For MSA instructions, this is a 10-bit signed immediate (scaled by
    213     // element size), otherwise it is a 16-bit signed immediate.
    214     unsigned OffsetBitSize =
    215         getLoadStoreOffsetSizeInBits(MI.getOpcode(), MI.getOperand(OpNo - 1));
    216     unsigned OffsetAlign = getLoadStoreOffsetAlign(MI.getOpcode());
    217 
    218     if (OffsetBitSize < 16 && isInt<16>(Offset) &&
    219         (!isIntN(OffsetBitSize, Offset) ||
    220          OffsetToAlignment(Offset, OffsetAlign) != 0)) {
    221       // If we have an offset that needs to fit into a signed n-bit immediate
    222       // (where n < 16) and doesn't, but does fit into 16-bits then use an ADDiu
    223       MachineBasicBlock &MBB = *MI.getParent();
    224       DebugLoc DL = II->getDebugLoc();
    225       const TargetRegisterClass *PtrRC =
    226           ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
    227       MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
    228       unsigned Reg = RegInfo.createVirtualRegister(PtrRC);
    229       const MipsSEInstrInfo &TII =
    230           *static_cast<const MipsSEInstrInfo *>(
    231               MBB.getParent()->getSubtarget().getInstrInfo());
    232       BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAddiuOp()), Reg)
    233           .addReg(FrameReg)
    234           .addImm(Offset);
    235 
    236       FrameReg = Reg;
    237       Offset = 0;
    238       IsKill = true;
    239     } else if (!isInt<16>(Offset)) {
    240       // Otherwise split the offset into 16-bit pieces and add it in multiple
    241       // instructions.
    242       MachineBasicBlock &MBB = *MI.getParent();
    243       DebugLoc DL = II->getDebugLoc();
    244       unsigned NewImm = 0;
    245       const MipsSEInstrInfo &TII =
    246           *static_cast<const MipsSEInstrInfo *>(
    247               MBB.getParent()->getSubtarget().getInstrInfo());
    248       unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL,
    249                                        OffsetBitSize == 16 ? &NewImm : nullptr);
    250       BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAdduOp()), Reg).addReg(FrameReg)
    251         .addReg(Reg, RegState::Kill);
    252 
    253       FrameReg = Reg;
    254       Offset = SignExtend64<16>(NewImm);
    255       IsKill = true;
    256     }
    257   }
    258 
    259   MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill);
    260   MI.getOperand(OpNo + 1).ChangeToImmediate(Offset);
    261 }
    262