xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Mips/MipsRegisterInfo.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===- MipsRegisterInfo.cpp - MIPS Register Information -------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains the MIPS implementation of the TargetRegisterInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "MipsRegisterInfo.h"
140b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h"
150b57cec5SDimitry Andric #include "Mips.h"
160b57cec5SDimitry Andric #include "MipsMachineFunction.h"
170b57cec5SDimitry Andric #include "MipsSubtarget.h"
180b57cec5SDimitry Andric #include "MipsTargetMachine.h"
190b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
200b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
280b57cec5SDimitry Andric #include "llvm/IR/Function.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
300b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
310b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
320b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
330b57cec5SDimitry Andric #include <cstdint>
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric using namespace llvm;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric #define DEBUG_TYPE "mips-reg-info"
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric #define GET_REGINFO_TARGET_DESC
400b57cec5SDimitry Andric #include "MipsGenRegisterInfo.inc"
410b57cec5SDimitry Andric 
MipsRegisterInfo()420b57cec5SDimitry Andric MipsRegisterInfo::MipsRegisterInfo() : MipsGenRegisterInfo(Mips::RA) {}
430b57cec5SDimitry Andric 
getPICCallReg()440b57cec5SDimitry Andric unsigned MipsRegisterInfo::getPICCallReg() { return Mips::T9; }
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric const TargetRegisterClass *
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const470b57cec5SDimitry Andric MipsRegisterInfo::getPointerRegClass(const MachineFunction &MF,
480b57cec5SDimitry Andric                                      unsigned Kind) const {
490b57cec5SDimitry Andric   MipsABIInfo ABI = MF.getSubtarget<MipsSubtarget>().getABI();
500b57cec5SDimitry Andric   MipsPtrClass PtrClassKind = static_cast<MipsPtrClass>(Kind);
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   switch (PtrClassKind) {
530b57cec5SDimitry Andric   case MipsPtrClass::Default:
540b57cec5SDimitry Andric     return ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
550b57cec5SDimitry Andric   case MipsPtrClass::GPR16MM:
560b57cec5SDimitry Andric     return &Mips::GPRMM16RegClass;
570b57cec5SDimitry Andric   case MipsPtrClass::StackPointer:
580b57cec5SDimitry Andric     return ABI.ArePtrs64bit() ? &Mips::SP64RegClass : &Mips::SP32RegClass;
590b57cec5SDimitry Andric   case MipsPtrClass::GlobalPointer:
600b57cec5SDimitry Andric     return ABI.ArePtrs64bit() ? &Mips::GP64RegClass : &Mips::GP32RegClass;
610b57cec5SDimitry Andric   }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   llvm_unreachable("Unknown pointer kind");
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric unsigned
getRegPressureLimit(const TargetRegisterClass * RC,MachineFunction & MF) const670b57cec5SDimitry Andric MipsRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
680b57cec5SDimitry Andric                                       MachineFunction &MF) const {
690b57cec5SDimitry Andric   switch (RC->getID()) {
700b57cec5SDimitry Andric   default:
710b57cec5SDimitry Andric     return 0;
720b57cec5SDimitry Andric   case Mips::GPR32RegClassID:
730b57cec5SDimitry Andric   case Mips::GPR64RegClassID:
740b57cec5SDimitry Andric   case Mips::DSPRRegClassID: {
750b57cec5SDimitry Andric     const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
760b57cec5SDimitry Andric     return 28 - TFI->hasFP(MF);
770b57cec5SDimitry Andric   }
780b57cec5SDimitry Andric   case Mips::FGR32RegClassID:
790b57cec5SDimitry Andric     return 32;
800b57cec5SDimitry Andric   case Mips::AFGR64RegClassID:
810b57cec5SDimitry Andric     return 16;
820b57cec5SDimitry Andric   case Mips::FGR64RegClassID:
830b57cec5SDimitry Andric     return 32;
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
880b57cec5SDimitry Andric // Callee Saved Registers methods
890b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric /// Mips Callee Saved Registers
920b57cec5SDimitry Andric const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const930b57cec5SDimitry Andric MipsRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
940b57cec5SDimitry Andric   const MipsSubtarget &Subtarget = MF->getSubtarget<MipsSubtarget>();
950b57cec5SDimitry Andric   const Function &F = MF->getFunction();
960b57cec5SDimitry Andric   if (F.hasFnAttribute("interrupt")) {
970b57cec5SDimitry Andric     if (Subtarget.hasMips64())
980b57cec5SDimitry Andric       return Subtarget.hasMips64r6() ? CSR_Interrupt_64R6_SaveList
990b57cec5SDimitry Andric                                      : CSR_Interrupt_64_SaveList;
1000b57cec5SDimitry Andric     else
1010b57cec5SDimitry Andric       return Subtarget.hasMips32r6() ? CSR_Interrupt_32R6_SaveList
1020b57cec5SDimitry Andric                                      : CSR_Interrupt_32_SaveList;
1030b57cec5SDimitry Andric   }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   if (Subtarget.isSingleFloat())
1060b57cec5SDimitry Andric     return CSR_SingleFloatOnly_SaveList;
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   if (Subtarget.isABI_N64())
1090b57cec5SDimitry Andric     return CSR_N64_SaveList;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   if (Subtarget.isABI_N32())
1120b57cec5SDimitry Andric     return CSR_N32_SaveList;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   if (Subtarget.isFP64bit())
1150b57cec5SDimitry Andric     return CSR_O32_FP64_SaveList;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   if (Subtarget.isFPXX())
1180b57cec5SDimitry Andric     return CSR_O32_FPXX_SaveList;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   return CSR_O32_SaveList;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID) const1240b57cec5SDimitry Andric MipsRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
1250b57cec5SDimitry Andric                                        CallingConv::ID) const {
1260b57cec5SDimitry Andric   const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
1270b57cec5SDimitry Andric   if (Subtarget.isSingleFloat())
1280b57cec5SDimitry Andric     return CSR_SingleFloatOnly_RegMask;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   if (Subtarget.isABI_N64())
1310b57cec5SDimitry Andric     return CSR_N64_RegMask;
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   if (Subtarget.isABI_N32())
1340b57cec5SDimitry Andric     return CSR_N32_RegMask;
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   if (Subtarget.isFP64bit())
1370b57cec5SDimitry Andric     return CSR_O32_FP64_RegMask;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   if (Subtarget.isFPXX())
1400b57cec5SDimitry Andric     return CSR_O32_FPXX_RegMask;
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   return CSR_O32_RegMask;
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric 
getMips16RetHelperMask()1450b57cec5SDimitry Andric const uint32_t *MipsRegisterInfo::getMips16RetHelperMask() {
1460b57cec5SDimitry Andric   return CSR_Mips16RetHelper_RegMask;
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric BitVector MipsRegisterInfo::
getReservedRegs(const MachineFunction & MF) const1500b57cec5SDimitry Andric getReservedRegs(const MachineFunction &MF) const {
1510b57cec5SDimitry Andric   static const MCPhysReg ReservedGPR32[] = {
1520b57cec5SDimitry Andric     Mips::ZERO, Mips::K0, Mips::K1, Mips::SP
1530b57cec5SDimitry Andric   };
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   static const MCPhysReg ReservedGPR64[] = {
1560b57cec5SDimitry Andric     Mips::ZERO_64, Mips::K0_64, Mips::K1_64, Mips::SP_64
1570b57cec5SDimitry Andric   };
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   BitVector Reserved(getNumRegs());
1600b57cec5SDimitry Andric   const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
1610b57cec5SDimitry Andric 
16204eeddc0SDimitry Andric   for (MCPhysReg R : ReservedGPR32)
16304eeddc0SDimitry Andric     Reserved.set(R);
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   // Reserve registers for the NaCl sandbox.
1660b57cec5SDimitry Andric   if (Subtarget.isTargetNaCl()) {
1670b57cec5SDimitry Andric     Reserved.set(Mips::T6);   // Reserved for control flow mask.
1680b57cec5SDimitry Andric     Reserved.set(Mips::T7);   // Reserved for memory access mask.
1690b57cec5SDimitry Andric     Reserved.set(Mips::T8);   // Reserved for thread pointer.
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric 
17204eeddc0SDimitry Andric   for (MCPhysReg R : ReservedGPR64)
17304eeddc0SDimitry Andric     Reserved.set(R);
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   // For mno-abicalls, GP is a program invariant!
1760b57cec5SDimitry Andric   if (!Subtarget.isABICalls()) {
1770b57cec5SDimitry Andric     Reserved.set(Mips::GP);
1780b57cec5SDimitry Andric     Reserved.set(Mips::GP_64);
1790b57cec5SDimitry Andric   }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   if (Subtarget.isFP64bit()) {
1820b57cec5SDimitry Andric     // Reserve all registers in AFGR64.
1830b57cec5SDimitry Andric     for (MCPhysReg Reg : Mips::AFGR64RegClass)
1840b57cec5SDimitry Andric       Reserved.set(Reg);
1850b57cec5SDimitry Andric   } else {
1860b57cec5SDimitry Andric     // Reserve all registers in FGR64.
1870b57cec5SDimitry Andric     for (MCPhysReg Reg : Mips::FGR64RegClass)
1880b57cec5SDimitry Andric       Reserved.set(Reg);
1890b57cec5SDimitry Andric   }
1900b57cec5SDimitry Andric   // Reserve FP if this function should have a dedicated frame pointer register.
1910b57cec5SDimitry Andric   if (Subtarget.getFrameLowering()->hasFP(MF)) {
1920b57cec5SDimitry Andric     if (Subtarget.inMips16Mode())
1930b57cec5SDimitry Andric       Reserved.set(Mips::S0);
1940b57cec5SDimitry Andric     else {
1950b57cec5SDimitry Andric       Reserved.set(Mips::FP);
1960b57cec5SDimitry Andric       Reserved.set(Mips::FP_64);
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric       // Reserve the base register if we need to both realign the stack and
1990b57cec5SDimitry Andric       // allocate variable-sized objects at runtime. This should test the
2000b57cec5SDimitry Andric       // same conditions as MipsFrameLowering::hasBP().
201fe6060f1SDimitry Andric       if (hasStackRealignment(MF) && MF.getFrameInfo().hasVarSizedObjects()) {
2020b57cec5SDimitry Andric         Reserved.set(Mips::S7);
2030b57cec5SDimitry Andric         Reserved.set(Mips::S7_64);
2040b57cec5SDimitry Andric       }
2050b57cec5SDimitry Andric     }
2060b57cec5SDimitry Andric   }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   // Reserve hardware registers.
2090b57cec5SDimitry Andric   Reserved.set(Mips::HWR29);
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   // Reserve DSP control register.
2120b57cec5SDimitry Andric   Reserved.set(Mips::DSPPos);
2130b57cec5SDimitry Andric   Reserved.set(Mips::DSPSCount);
2140b57cec5SDimitry Andric   Reserved.set(Mips::DSPCarry);
2150b57cec5SDimitry Andric   Reserved.set(Mips::DSPEFI);
2160b57cec5SDimitry Andric   Reserved.set(Mips::DSPOutFlag);
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   // Reserve MSA control registers.
2190b57cec5SDimitry Andric   for (MCPhysReg Reg : Mips::MSACtrlRegClass)
2200b57cec5SDimitry Andric     Reserved.set(Reg);
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   // Reserve RA if in mips16 mode.
2230b57cec5SDimitry Andric   if (Subtarget.inMips16Mode()) {
2240b57cec5SDimitry Andric     const MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
2250b57cec5SDimitry Andric     Reserved.set(Mips::RA);
2260b57cec5SDimitry Andric     Reserved.set(Mips::RA_64);
2270b57cec5SDimitry Andric     Reserved.set(Mips::T0);
2280b57cec5SDimitry Andric     Reserved.set(Mips::T1);
2290b57cec5SDimitry Andric     if (MF.getFunction().hasFnAttribute("saveS2") || MipsFI->hasSaveS2())
2300b57cec5SDimitry Andric       Reserved.set(Mips::S2);
2310b57cec5SDimitry Andric   }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric   // Reserve GP if small section is used.
2340b57cec5SDimitry Andric   if (Subtarget.useSmallSection()) {
2350b57cec5SDimitry Andric     Reserved.set(Mips::GP);
2360b57cec5SDimitry Andric     Reserved.set(Mips::GP_64);
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   return Reserved;
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric // FrameIndex represent objects inside a abstract stack.
2430b57cec5SDimitry Andric // We must replace FrameIndex with an stack/frame pointer
2440b57cec5SDimitry Andric // direct reference.
245*bdd1243dSDimitry Andric bool MipsRegisterInfo::
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const2460b57cec5SDimitry Andric eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
2470b57cec5SDimitry Andric                     unsigned FIOperandNum, RegScavenger *RS) const {
2480b57cec5SDimitry Andric   MachineInstr &MI = *II;
2490b57cec5SDimitry Andric   MachineFunction &MF = *MI.getParent()->getParent();
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   LLVM_DEBUG(errs() << "\nFunction : " << MF.getName() << "\n";
2520b57cec5SDimitry Andric              errs() << "<--------->\n"
2530b57cec5SDimitry Andric                     << MI);
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
2560b57cec5SDimitry Andric   uint64_t stackSize = MF.getFrameInfo().getStackSize();
2570b57cec5SDimitry Andric   int64_t spOffset = MF.getFrameInfo().getObjectOffset(FrameIndex);
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   LLVM_DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n"
2600b57cec5SDimitry Andric                     << "spOffset   : " << spOffset << "\n"
2610b57cec5SDimitry Andric                     << "stackSize  : " << stackSize << "\n"
2620b57cec5SDimitry Andric                     << "alignment  : "
2635ffd83dbSDimitry Andric                     << DebugStr(MF.getFrameInfo().getObjectAlign(FrameIndex))
2640b57cec5SDimitry Andric                     << "\n");
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   eliminateFI(MI, FIOperandNum, FrameIndex, stackSize, spOffset);
267*bdd1243dSDimitry Andric   return false;
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric Register MipsRegisterInfo::
getFrameRegister(const MachineFunction & MF) const2710b57cec5SDimitry Andric getFrameRegister(const MachineFunction &MF) const {
2720b57cec5SDimitry Andric   const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
2730b57cec5SDimitry Andric   const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
2740b57cec5SDimitry Andric   bool IsN64 =
2750b57cec5SDimitry Andric       static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64();
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric   if (Subtarget.inMips16Mode())
2780b57cec5SDimitry Andric     return TFI->hasFP(MF) ? Mips::S0 : Mips::SP;
2790b57cec5SDimitry Andric   else
2800b57cec5SDimitry Andric     return TFI->hasFP(MF) ? (IsN64 ? Mips::FP_64 : Mips::FP) :
2810b57cec5SDimitry Andric                             (IsN64 ? Mips::SP_64 : Mips::SP);
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric 
canRealignStack(const MachineFunction & MF) const2840b57cec5SDimitry Andric bool MipsRegisterInfo::canRealignStack(const MachineFunction &MF) const {
2850b57cec5SDimitry Andric   // Avoid realigning functions that explicitly do not want to be realigned.
2860b57cec5SDimitry Andric   // Normally, we should report an error when a function should be dynamically
2870b57cec5SDimitry Andric   // realigned but also has the attribute no-realign-stack. Unfortunately,
2880b57cec5SDimitry Andric   // with this attribute, MachineFrameInfo clamps each new object's alignment
2890b57cec5SDimitry Andric   // to that of the stack's alignment as specified by the ABI. As a result,
2900b57cec5SDimitry Andric   // the information of whether we have objects with larger alignment
2910b57cec5SDimitry Andric   // requirement than the stack's alignment is already lost at this point.
2920b57cec5SDimitry Andric   if (!TargetRegisterInfo::canRealignStack(MF))
2930b57cec5SDimitry Andric     return false;
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
2960b57cec5SDimitry Andric   unsigned FP = Subtarget.isGP32bit() ? Mips::FP : Mips::FP_64;
2970b57cec5SDimitry Andric   unsigned BP = Subtarget.isGP32bit() ? Mips::S7 : Mips::S7_64;
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   // Support dynamic stack realignment for all targets except Mips16.
3000b57cec5SDimitry Andric   if (Subtarget.inMips16Mode())
3010b57cec5SDimitry Andric     return false;
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   // We can't perform dynamic stack realignment if we can't reserve the
3040b57cec5SDimitry Andric   // frame pointer register.
3050b57cec5SDimitry Andric   if (!MF.getRegInfo().canReserveReg(FP))
3060b57cec5SDimitry Andric     return false;
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   // We can realign the stack if we know the maximum call frame size and we
3090b57cec5SDimitry Andric   // don't have variable sized objects.
3100b57cec5SDimitry Andric   if (Subtarget.getFrameLowering()->hasReservedCallFrame(MF))
3110b57cec5SDimitry Andric     return true;
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric   // We have to reserve the base pointer register in the presence of variable
3140b57cec5SDimitry Andric   // sized objects.
3150b57cec5SDimitry Andric   return MF.getRegInfo().canReserveReg(BP);
3160b57cec5SDimitry Andric }
317