1249259Sdim//===- AArch64RegisterInfo.cpp - AArch64 Register Information -------------===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim// This file contains the AArch64 implementation of the TargetRegisterInfo
11249259Sdim// class.
12249259Sdim//
13249259Sdim//===----------------------------------------------------------------------===//
14249259Sdim
15249259Sdim
16249259Sdim#include "AArch64RegisterInfo.h"
17249259Sdim#include "AArch64FrameLowering.h"
18249259Sdim#include "AArch64MachineFunctionInfo.h"
19249259Sdim#include "AArch64TargetMachine.h"
20249259Sdim#include "MCTargetDesc/AArch64MCTargetDesc.h"
21249259Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
22249259Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
23249259Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
24249259Sdim#include "llvm/CodeGen/RegisterScavenging.h"
25249259Sdim#include "llvm/ADT/BitVector.h"
26249259Sdim
27249259Sdim#define GET_REGINFO_TARGET_DESC
28249259Sdim#include "AArch64GenRegisterInfo.inc"
29249259Sdim
30249259Sdimusing namespace llvm;
31249259Sdim
32263508SdimAArch64RegisterInfo::AArch64RegisterInfo()
33263508Sdim  : AArch64GenRegisterInfo(AArch64::X30) {
34249259Sdim}
35249259Sdim
36249259Sdimconst uint16_t *
37249259SdimAArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
38249259Sdim  return CSR_PCS_SaveList;
39249259Sdim}
40249259Sdim
41249259Sdimconst uint32_t*
42249259SdimAArch64RegisterInfo::getCallPreservedMask(CallingConv::ID) const {
43249259Sdim  return CSR_PCS_RegMask;
44249259Sdim}
45249259Sdim
46249259Sdimconst uint32_t *AArch64RegisterInfo::getTLSDescCallPreservedMask() const {
47249259Sdim  return TLSDesc_RegMask;
48249259Sdim}
49249259Sdim
50249259Sdimconst TargetRegisterClass *
51249259SdimAArch64RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
52249259Sdim  if (RC == &AArch64::FlagClassRegClass)
53249259Sdim    return &AArch64::GPR64RegClass;
54249259Sdim
55249259Sdim  return RC;
56249259Sdim}
57249259Sdim
58249259Sdim
59249259Sdim
60249259SdimBitVector
61249259SdimAArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
62249259Sdim  BitVector Reserved(getNumRegs());
63249259Sdim  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
64249259Sdim
65249259Sdim  Reserved.set(AArch64::XSP);
66249259Sdim  Reserved.set(AArch64::WSP);
67249259Sdim
68249259Sdim  Reserved.set(AArch64::XZR);
69249259Sdim  Reserved.set(AArch64::WZR);
70249259Sdim
71249259Sdim  if (TFI->hasFP(MF)) {
72249259Sdim    Reserved.set(AArch64::X29);
73249259Sdim    Reserved.set(AArch64::W29);
74249259Sdim  }
75249259Sdim
76249259Sdim  return Reserved;
77249259Sdim}
78249259Sdim
79249259Sdimvoid
80249259SdimAArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBI,
81249259Sdim                                         int SPAdj,
82249259Sdim                                         unsigned FIOperandNum,
83249259Sdim                                         RegScavenger *RS) const {
84249259Sdim  assert(SPAdj == 0 && "Cannot deal with nonzero SPAdj yet");
85249259Sdim  MachineInstr &MI = *MBBI;
86249259Sdim  MachineBasicBlock &MBB = *MI.getParent();
87249259Sdim  MachineFunction &MF = *MBB.getParent();
88249259Sdim  MachineFrameInfo *MFI = MF.getFrameInfo();
89249259Sdim  const AArch64FrameLowering *TFI =
90249259Sdim   static_cast<const AArch64FrameLowering *>(MF.getTarget().getFrameLowering());
91249259Sdim
92249259Sdim  // In order to work out the base and offset for addressing, the FrameLowering
93249259Sdim  // code needs to know (sometimes) whether the instruction is storing/loading a
94249259Sdim  // callee-saved register, or whether it's a more generic
95249259Sdim  // operation. Fortunately the frame indices are used *only* for that purpose
96249259Sdim  // and are contiguous, so we can check here.
97249259Sdim  const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
98249259Sdim  int MinCSFI = 0;
99249259Sdim  int MaxCSFI = -1;
100249259Sdim
101249259Sdim  if (CSI.size()) {
102249259Sdim    MinCSFI = CSI[0].getFrameIdx();
103249259Sdim    MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
104249259Sdim  }
105249259Sdim
106249259Sdim  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
107249259Sdim  bool IsCalleeSaveOp = FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI;
108249259Sdim
109249259Sdim  unsigned FrameReg;
110249259Sdim  int64_t Offset;
111249259Sdim  Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg, SPAdj,
112249259Sdim                                           IsCalleeSaveOp);
113249259Sdim
114249259Sdim  Offset += MI.getOperand(FIOperandNum + 1).getImm();
115249259Sdim
116249259Sdim  // DBG_VALUE instructions have no real restrictions so they can be handled
117249259Sdim  // easily.
118249259Sdim  if (MI.isDebugValue()) {
119249259Sdim    MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/ false);
120249259Sdim    MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
121249259Sdim    return;
122249259Sdim  }
123249259Sdim
124263508Sdim  const AArch64InstrInfo &TII =
125263508Sdim    *static_cast<const AArch64InstrInfo*>(MF.getTarget().getInstrInfo());
126249259Sdim  int MinOffset, MaxOffset, OffsetScale;
127249259Sdim  if (MI.getOpcode() == AArch64::ADDxxi_lsl0_s) {
128249259Sdim    MinOffset = 0;
129249259Sdim    MaxOffset = 0xfff;
130249259Sdim    OffsetScale = 1;
131249259Sdim  } else {
132249259Sdim    // Load/store of a stack object
133249259Sdim    TII.getAddressConstraints(MI, OffsetScale, MinOffset, MaxOffset);
134249259Sdim  }
135249259Sdim
136249259Sdim  // The frame lowering has told us a base and offset it thinks we should use to
137249259Sdim  // access this variable, but it's still up to us to make sure the values are
138249259Sdim  // legal for the instruction in question.
139249259Sdim  if (Offset % OffsetScale != 0 || Offset < MinOffset || Offset > MaxOffset) {
140249259Sdim    unsigned BaseReg =
141249259Sdim      MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
142249259Sdim    emitRegUpdate(MBB, MBBI, MBBI->getDebugLoc(), TII,
143249259Sdim                  BaseReg, FrameReg, BaseReg, Offset);
144249259Sdim    FrameReg = BaseReg;
145249259Sdim    Offset = 0;
146249259Sdim  }
147249259Sdim
148249259Sdim  // Negative offsets are expected if we address from FP, but for
149249259Sdim  // now this checks nothing has gone horribly wrong.
150249259Sdim  assert(Offset >= 0 && "Unexpected negative offset from SP");
151249259Sdim
152249259Sdim  MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, true);
153249259Sdim  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset / OffsetScale);
154249259Sdim}
155249259Sdim
156249259Sdimunsigned
157249259SdimAArch64RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
158249259Sdim  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
159249259Sdim
160249259Sdim  if (TFI->hasFP(MF))
161249259Sdim    return AArch64::X29;
162249259Sdim  else
163249259Sdim    return AArch64::XSP;
164249259Sdim}
165249259Sdim
166249259Sdimbool
167249259SdimAArch64RegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
168249259Sdim  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
169249259Sdim  const AArch64FrameLowering *AFI
170249259Sdim    = static_cast<const AArch64FrameLowering*>(TFI);
171249259Sdim  return AFI->useFPForAddressing(MF);
172249259Sdim}
173