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