1 | //===-- ARMBaseRegisterInfo.h - ARM Register Information Impl ---*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains the base ARM implementation of TargetRegisterInfo class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_LIB_TARGET_ARM_ARMBASEREGISTERINFO_H |
14 | #define LLVM_LIB_TARGET_ARM_ARMBASEREGISTERINFO_H |
15 | |
16 | #include "MCTargetDesc/ARMBaseInfo.h" |
17 | #include "llvm/CodeGen/MachineBasicBlock.h" |
18 | #include "llvm/CodeGen/MachineInstr.h" |
19 | #include "llvm/CodeGen/TargetRegisterInfo.h" |
20 | #include "llvm/IR/CallingConv.h" |
21 | #include "llvm/MC/MCRegisterInfo.h" |
22 | #include <cstdint> |
23 | |
24 | #define |
25 | #include "ARMGenRegisterInfo.inc" |
26 | |
27 | namespace llvm { |
28 | |
29 | class LiveIntervals; |
30 | |
31 | /// Register allocation hints. |
32 | namespace ARMRI { |
33 | |
34 | enum { |
35 | // Used for LDRD register pairs |
36 | RegPairOdd = 1, |
37 | RegPairEven = 2, |
38 | // Used to hint for lr in t2DoLoopStart |
39 | RegLR = 3 |
40 | }; |
41 | |
42 | } // end namespace ARMRI |
43 | |
44 | /// isARMArea1Register - Returns true if the register is a low register (r0-r7) |
45 | /// or a stack/pc register that we should push/pop. |
46 | static inline bool isARMArea1Register(unsigned Reg, bool SplitFramePushPop) { |
47 | using namespace ARM; |
48 | |
49 | switch (Reg) { |
50 | case R0: case R1: case R2: case R3: |
51 | case R4: case R5: case R6: case R7: |
52 | case LR: case SP: case PC: |
53 | return true; |
54 | case R8: case R9: case R10: case R11: case R12: |
55 | // For iOS we want r7 and lr to be next to each other. |
56 | return !SplitFramePushPop; |
57 | default: |
58 | return false; |
59 | } |
60 | } |
61 | |
62 | static inline bool isARMArea2Register(unsigned Reg, bool SplitFramePushPop) { |
63 | using namespace ARM; |
64 | |
65 | switch (Reg) { |
66 | case R8: case R9: case R10: case R11: case R12: |
67 | // iOS has this second area. |
68 | return SplitFramePushPop; |
69 | default: |
70 | return false; |
71 | } |
72 | } |
73 | |
74 | static inline bool isSplitFPArea1Register(unsigned Reg, |
75 | bool SplitFramePushPop) { |
76 | using namespace ARM; |
77 | |
78 | switch (Reg) { |
79 | case R0: case R1: case R2: case R3: |
80 | case R4: case R5: case R6: case R7: |
81 | case R8: case R9: case R10: case R12: |
82 | case SP: case PC: |
83 | return true; |
84 | default: |
85 | return false; |
86 | } |
87 | } |
88 | |
89 | static inline bool isSplitFPArea2Register(unsigned Reg, |
90 | bool SplitFramePushPop) { |
91 | using namespace ARM; |
92 | |
93 | switch (Reg) { |
94 | case R11: case LR: |
95 | return true; |
96 | default: |
97 | return false; |
98 | } |
99 | } |
100 | |
101 | static inline bool isARMArea3Register(unsigned Reg, bool SplitFramePushPop) { |
102 | using namespace ARM; |
103 | |
104 | switch (Reg) { |
105 | case D15: case D14: case D13: case D12: |
106 | case D11: case D10: case D9: case D8: |
107 | case D7: case D6: case D5: case D4: |
108 | case D3: case D2: case D1: case D0: |
109 | case D31: case D30: case D29: case D28: |
110 | case D27: case D26: case D25: case D24: |
111 | case D23: case D22: case D21: case D20: |
112 | case D19: case D18: case D17: case D16: |
113 | return true; |
114 | default: |
115 | return false; |
116 | } |
117 | } |
118 | |
119 | static inline bool isCalleeSavedRegister(unsigned Reg, |
120 | const MCPhysReg *CSRegs) { |
121 | for (unsigned i = 0; CSRegs[i]; ++i) |
122 | if (Reg == CSRegs[i]) |
123 | return true; |
124 | return false; |
125 | } |
126 | |
127 | class ARMBaseRegisterInfo : public ARMGenRegisterInfo { |
128 | protected: |
129 | /// BasePtr - ARM physical register used as a base ptr in complex stack |
130 | /// frames. I.e., when we need a 3rd base, not just SP and FP, due to |
131 | /// variable size stack objects. |
132 | unsigned BasePtr = ARM::R6; |
133 | |
134 | // Can be only subclassed. |
135 | explicit ARMBaseRegisterInfo(); |
136 | |
137 | public: |
138 | /// Code Generation virtual methods... |
139 | const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; |
140 | const MCPhysReg * |
141 | getCalleeSavedRegsViaCopy(const MachineFunction *MF) const; |
142 | const uint32_t *getCallPreservedMask(const MachineFunction &MF, |
143 | CallingConv::ID) const override; |
144 | const uint32_t *getNoPreservedMask() const override; |
145 | const uint32_t *getTLSCallPreservedMask(const MachineFunction &MF) const; |
146 | const uint32_t *getSjLjDispatchPreservedMask(const MachineFunction &MF) const; |
147 | |
148 | /// getThisReturnPreservedMask - Returns a call preserved mask specific to the |
149 | /// case that 'returned' is on an i32 first argument if the calling convention |
150 | /// is one that can (partially) model this attribute with a preserved mask |
151 | /// (i.e. it is a calling convention that uses the same register for the first |
152 | /// i32 argument and an i32 return value) |
153 | /// |
154 | /// Should return NULL in the case that the calling convention does not have |
155 | /// this property |
156 | const uint32_t *getThisReturnPreservedMask(const MachineFunction &MF, |
157 | CallingConv::ID) const; |
158 | |
159 | ArrayRef<MCPhysReg> |
160 | getIntraCallClobberedRegs(const MachineFunction *MF) const override; |
161 | |
162 | BitVector getReservedRegs(const MachineFunction &MF) const override; |
163 | bool isAsmClobberable(const MachineFunction &MF, |
164 | MCRegister PhysReg) const override; |
165 | bool isInlineAsmReadOnlyReg(const MachineFunction &MF, |
166 | unsigned PhysReg) const override; |
167 | |
168 | const TargetRegisterClass * |
169 | getPointerRegClass(const MachineFunction &MF, |
170 | unsigned Kind = 0) const override; |
171 | const TargetRegisterClass * |
172 | getCrossCopyRegClass(const TargetRegisterClass *RC) const override; |
173 | |
174 | const TargetRegisterClass * |
175 | getLargestLegalSuperClass(const TargetRegisterClass *RC, |
176 | const MachineFunction &MF) const override; |
177 | |
178 | unsigned getRegPressureLimit(const TargetRegisterClass *RC, |
179 | MachineFunction &MF) const override; |
180 | |
181 | bool getRegAllocationHints(Register VirtReg, ArrayRef<MCPhysReg> Order, |
182 | SmallVectorImpl<MCPhysReg> &Hints, |
183 | const MachineFunction &MF, const VirtRegMap *VRM, |
184 | const LiveRegMatrix *Matrix) const override; |
185 | |
186 | void updateRegAllocHint(Register Reg, Register NewReg, |
187 | MachineFunction &MF) const override; |
188 | |
189 | bool hasBasePointer(const MachineFunction &MF) const; |
190 | |
191 | bool canRealignStack(const MachineFunction &MF) const override; |
192 | int64_t getFrameIndexInstrOffset(const MachineInstr *MI, |
193 | int Idx) const override; |
194 | bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const override; |
195 | Register materializeFrameBaseRegister(MachineBasicBlock *MBB, int FrameIdx, |
196 | int64_t Offset) const override; |
197 | void resolveFrameIndex(MachineInstr &MI, Register BaseReg, |
198 | int64_t Offset) const override; |
199 | bool isFrameOffsetLegal(const MachineInstr *MI, Register BaseReg, |
200 | int64_t Offset) const override; |
201 | |
202 | bool cannotEliminateFrame(const MachineFunction &MF) const; |
203 | |
204 | // Debug information queries. |
205 | Register getFrameRegister(const MachineFunction &MF) const override; |
206 | Register getBaseRegister() const { return BasePtr; } |
207 | |
208 | /// emitLoadConstPool - Emits a load from constpool to materialize the |
209 | /// specified immediate. |
210 | virtual void |
211 | emitLoadConstPool(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, |
212 | const DebugLoc &dl, Register DestReg, unsigned SubIdx, |
213 | int Val, ARMCC::CondCodes Pred = ARMCC::AL, |
214 | Register PredReg = Register(), |
215 | unsigned MIFlags = MachineInstr::NoFlags) const; |
216 | |
217 | /// Code Generation virtual methods... |
218 | bool requiresRegisterScavenging(const MachineFunction &MF) const override; |
219 | |
220 | bool requiresFrameIndexScavenging(const MachineFunction &MF) const override; |
221 | |
222 | bool requiresVirtualBaseRegisters(const MachineFunction &MF) const override; |
223 | |
224 | bool eliminateFrameIndex(MachineBasicBlock::iterator II, |
225 | int SPAdj, unsigned FIOperandNum, |
226 | RegScavenger *RS = nullptr) const override; |
227 | |
228 | /// SrcRC and DstRC will be morphed into NewRC if this returns true |
229 | bool shouldCoalesce(MachineInstr *MI, |
230 | const TargetRegisterClass *SrcRC, |
231 | unsigned SubReg, |
232 | const TargetRegisterClass *DstRC, |
233 | unsigned DstSubReg, |
234 | const TargetRegisterClass *NewRC, |
235 | LiveIntervals &LIS) const override; |
236 | |
237 | bool shouldRewriteCopySrc(const TargetRegisterClass *DefRC, |
238 | unsigned DefSubReg, |
239 | const TargetRegisterClass *SrcRC, |
240 | unsigned SrcSubReg) const override; |
241 | |
242 | int getSEHRegNum(unsigned i) const { return getEncodingValue(RegNo: i); } |
243 | |
244 | const TargetRegisterClass * |
245 | getLargestSuperClass(const TargetRegisterClass *RC) const override { |
246 | if (ARM::MQPRRegClass.hasSubClassEq(RC)) |
247 | return &ARM::MQPRRegClass; |
248 | if (ARM::SPRRegClass.hasSubClassEq(RC)) |
249 | return &ARM::SPRRegClass; |
250 | if (ARM::DPR_VFP2RegClass.hasSubClassEq(RC)) |
251 | return &ARM::DPR_VFP2RegClass; |
252 | if (ARM::GPRRegClass.hasSubClassEq(RC)) |
253 | return &ARM::GPRRegClass; |
254 | return RC; |
255 | } |
256 | |
257 | bool doesRegClassHavePseudoInitUndef( |
258 | const TargetRegisterClass *RC) const override { |
259 | (void)RC; |
260 | // For the ARM Architecture we want to always return true because all |
261 | // required PseudoInitUndef types have been added. If compilation fails due |
262 | // to `Unexpected register class`, this is likely to be because the specific |
263 | // register being used is not support by Init Undef and needs the Pseudo |
264 | // Instruction adding to ARMInstrInfo.td. If this is implemented as a |
265 | // conditional check, this could create a false positive where Init Undef is |
266 | // not running, skipping the instruction and moving to the next. This could |
267 | // lead to illegal instructions being generated by the register allocator. |
268 | return true; |
269 | } |
270 | }; |
271 | |
272 | } // end namespace llvm |
273 | |
274 | #endif // LLVM_LIB_TARGET_ARM_ARMBASEREGISTERINFO_H |
275 | |