Home | History | Annotate | Download | only in AArch64
      1 //===- AArch64RegisterInfo.cpp - AArch64 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 AArch64 implementation of the TargetRegisterInfo
     11 // class.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 
     16 #include "AArch64RegisterInfo.h"
     17 #include "AArch64FrameLowering.h"
     18 #include "AArch64MachineFunctionInfo.h"
     19 #include "AArch64TargetMachine.h"
     20 #include "MCTargetDesc/AArch64MCTargetDesc.h"
     21 #include "llvm/CodeGen/MachineFrameInfo.h"
     22 #include "llvm/CodeGen/MachineInstrBuilder.h"
     23 #include "llvm/CodeGen/MachineRegisterInfo.h"
     24 #include "llvm/CodeGen/RegisterScavenging.h"
     25 #include "llvm/ADT/BitVector.h"
     26 
     27 #define GET_REGINFO_TARGET_DESC
     28 #include "AArch64GenRegisterInfo.inc"
     29 
     30 using namespace llvm;
     31 
     32 AArch64RegisterInfo::AArch64RegisterInfo()
     33   : AArch64GenRegisterInfo(AArch64::X30) {
     34 }
     35 
     36 const uint16_t *
     37 AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
     38   return CSR_PCS_SaveList;
     39 }
     40 
     41 const uint32_t*
     42 AArch64RegisterInfo::getCallPreservedMask(CallingConv::ID) const {
     43   return CSR_PCS_RegMask;
     44 }
     45 
     46 const uint32_t *AArch64RegisterInfo::getTLSDescCallPreservedMask() const {
     47   return TLSDesc_RegMask;
     48 }
     49 
     50 const TargetRegisterClass *
     51 AArch64RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
     52   if (RC == &AArch64::FlagClassRegClass)
     53     return &AArch64::GPR64RegClass;
     54 
     55   return RC;
     56 }
     57 
     58 
     59 
     60 BitVector
     61 AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
     62   BitVector Reserved(getNumRegs());
     63   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
     64 
     65   Reserved.set(AArch64::XSP);
     66   Reserved.set(AArch64::WSP);
     67 
     68   Reserved.set(AArch64::XZR);
     69   Reserved.set(AArch64::WZR);
     70 
     71   if (TFI->hasFP(MF)) {
     72     Reserved.set(AArch64::X29);
     73     Reserved.set(AArch64::W29);
     74   }
     75 
     76   return Reserved;
     77 }
     78 
     79 void
     80 AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBI,
     81                                          int SPAdj,
     82                                          unsigned FIOperandNum,
     83                                          RegScavenger *RS) const {
     84   assert(SPAdj == 0 && "Cannot deal with nonzero SPAdj yet");
     85   MachineInstr &MI = *MBBI;
     86   MachineBasicBlock &MBB = *MI.getParent();
     87   MachineFunction &MF = *MBB.getParent();
     88   MachineFrameInfo *MFI = MF.getFrameInfo();
     89   const AArch64FrameLowering *TFI =
     90    static_cast<const AArch64FrameLowering *>(MF.getTarget().getFrameLowering());
     91 
     92   // In order to work out the base and offset for addressing, the FrameLowering
     93   // code needs to know (sometimes) whether the instruction is storing/loading a
     94   // callee-saved register, or whether it's a more generic
     95   // operation. Fortunately the frame indices are used *only* for that purpose
     96   // and are contiguous, so we can check here.
     97   const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
     98   int MinCSFI = 0;
     99   int MaxCSFI = -1;
    100 
    101   if (CSI.size()) {
    102     MinCSFI = CSI[0].getFrameIdx();
    103     MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
    104   }
    105 
    106   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
    107   bool IsCalleeSaveOp = FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI;
    108 
    109   unsigned FrameReg;
    110   int64_t Offset;
    111   Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg, SPAdj,
    112                                            IsCalleeSaveOp);
    113 
    114   Offset += MI.getOperand(FIOperandNum + 1).getImm();
    115 
    116   // DBG_VALUE instructions have no real restrictions so they can be handled
    117   // easily.
    118   if (MI.isDebugValue()) {
    119     MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/ false);
    120     MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
    121     return;
    122   }
    123 
    124   const AArch64InstrInfo &TII =
    125     *static_cast<const AArch64InstrInfo*>(MF.getTarget().getInstrInfo());
    126   int MinOffset, MaxOffset, OffsetScale;
    127   if (MI.getOpcode() == AArch64::ADDxxi_lsl0_s) {
    128     MinOffset = 0;
    129     MaxOffset = 0xfff;
    130     OffsetScale = 1;
    131   } else {
    132     // Load/store of a stack object
    133     TII.getAddressConstraints(MI, OffsetScale, MinOffset, MaxOffset);
    134   }
    135 
    136   // The frame lowering has told us a base and offset it thinks we should use to
    137   // access this variable, but it's still up to us to make sure the values are
    138   // legal for the instruction in question.
    139   if (Offset % OffsetScale != 0 || Offset < MinOffset || Offset > MaxOffset) {
    140     unsigned BaseReg =
    141       MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
    142     emitRegUpdate(MBB, MBBI, MBBI->getDebugLoc(), TII,
    143                   BaseReg, FrameReg, BaseReg, Offset);
    144     FrameReg = BaseReg;
    145     Offset = 0;
    146   }
    147 
    148   // Negative offsets are expected if we address from FP, but for
    149   // now this checks nothing has gone horribly wrong.
    150   assert(Offset >= 0 && "Unexpected negative offset from SP");
    151 
    152   MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, true);
    153   MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset / OffsetScale);
    154 }
    155 
    156 unsigned
    157 AArch64RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
    158   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
    159 
    160   if (TFI->hasFP(MF))
    161     return AArch64::X29;
    162   else
    163     return AArch64::XSP;
    164 }
    165 
    166 bool
    167 AArch64RegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
    168   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
    169   const AArch64FrameLowering *AFI
    170     = static_cast<const AArch64FrameLowering*>(TFI);
    171   return AFI->useFPForAddressing(MF);
    172 }
    173