LLVM 22.0.0git
HexagonRegisterInfo.cpp
Go to the documentation of this file.
1//===-- HexagonRegisterInfo.cpp - Hexagon Register Information ------------===//
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 Hexagon implementation of the TargetRegisterInfo
10// class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "HexagonRegisterInfo.h"
16#include "HexagonSubtarget.h"
17#include "llvm/ADT/BitVector.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/SmallSet.h"
29#include "llvm/IR/Function.h"
30#include "llvm/IR/Type.h"
32#include "llvm/Support/Debug.h"
36
37#define GET_REGINFO_TARGET_DESC
38#include "HexagonGenRegisterInfo.inc"
39
40using namespace llvm;
41
43 "hexagon-frame-index-search-range", cl::init(32), cl::Hidden,
44 cl::desc("Limit on instruction search range in frame index elimination"));
45
47 "hexagon-frame-index-reuse-limit", cl::init(~0), cl::Hidden,
48 cl::desc("Limit on the number of reused registers in frame index "
49 "elimination"));
50
52 : HexagonGenRegisterInfo(Hexagon::R31, 0/*DwarfFlavor*/, 0/*EHFlavor*/,
53 0/*PC*/, HwMode) {}
54
55
57 return R == Hexagon::R0 || R == Hexagon::R1 || R == Hexagon::R2 ||
58 R == Hexagon::R3 || R == Hexagon::D0 || R == Hexagon::D1;
59}
60
61const MCPhysReg *
63 const TargetRegisterClass *RC) const {
64 using namespace Hexagon;
65
66 static const MCPhysReg Int32[] = {
67 R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, 0
68 };
69 static const MCPhysReg Int64[] = {
70 D0, D1, D2, D3, D4, D5, D6, D7, 0
71 };
72 static const MCPhysReg Pred[] = {
73 P0, P1, P2, P3, 0
74 };
75 static const MCPhysReg VecSgl[] = {
76 V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13,
77 V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27,
78 V28, V29, V30, V31, 0
79 };
80 static const MCPhysReg VecDbl[] = {
81 W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, 0
82 };
83 static const MCPhysReg VecPred[] = {
84 Q0, Q1, Q2, Q3, 0
85 };
86
87 switch (RC->getID()) {
88 case IntRegsRegClassID:
89 return Int32;
90 case DoubleRegsRegClassID:
91 return Int64;
92 case PredRegsRegClassID:
93 return Pred;
94 case HvxVRRegClassID:
95 return VecSgl;
96 case HvxWRRegClassID:
97 return VecDbl;
98 case HvxQRRegClassID:
99 return VecPred;
100 default:
101 break;
102 }
103
104 static const MCPhysReg Empty[] = { 0 };
105#ifndef NDEBUG
106 dbgs() << "Register class: " << getRegClassName(RC) << "\n";
107#endif
108 llvm_unreachable("Unexpected register class");
109 return Empty;
110}
111
112
113const MCPhysReg *
115 static const MCPhysReg CalleeSavedRegsV3[] = {
116 Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19,
117 Hexagon::R20, Hexagon::R21, Hexagon::R22, Hexagon::R23,
118 Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0
119 };
120
121 // Functions that contain a call to __builtin_eh_return also save the first 4
122 // parameter registers.
123 static const MCPhysReg CalleeSavedRegsV3EHReturn[] = {
124 Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3,
125 Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19,
126 Hexagon::R20, Hexagon::R21, Hexagon::R22, Hexagon::R23,
127 Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0
128 };
129
130 bool HasEHReturn = MF->getInfo<HexagonMachineFunctionInfo>()->hasEHReturn();
131
132 return HasEHReturn ? CalleeSavedRegsV3EHReturn : CalleeSavedRegsV3;
133}
134
135
137 const MachineFunction &MF, CallingConv::ID) const {
138 return HexagonCSR_RegMask;
139}
140
141
143 const {
144 BitVector Reserved(getNumRegs());
145 Reserved.set(Hexagon::R29);
146 Reserved.set(Hexagon::R30);
147 Reserved.set(Hexagon::R31);
148 Reserved.set(Hexagon::VTMP);
149
150 // Guest registers.
151 Reserved.set(Hexagon::GELR); // G0
152 Reserved.set(Hexagon::GSR); // G1
153 Reserved.set(Hexagon::GOSP); // G2
154 Reserved.set(Hexagon::G3); // G3
155
156 // Control registers.
157 Reserved.set(Hexagon::SA0); // C0
158 Reserved.set(Hexagon::LC0); // C1
159 Reserved.set(Hexagon::SA1); // C2
160 Reserved.set(Hexagon::LC1); // C3
161 Reserved.set(Hexagon::P3_0); // C4
162 Reserved.set(Hexagon::USR); // C8
163 Reserved.set(Hexagon::PC); // C9
164 Reserved.set(Hexagon::UGP); // C10
165 Reserved.set(Hexagon::GP); // C11
166 Reserved.set(Hexagon::CS0); // C12
167 Reserved.set(Hexagon::CS1); // C13
168 Reserved.set(Hexagon::UPCYCLELO); // C14
169 Reserved.set(Hexagon::UPCYCLEHI); // C15
170 Reserved.set(Hexagon::FRAMELIMIT); // C16
171 Reserved.set(Hexagon::FRAMEKEY); // C17
172 Reserved.set(Hexagon::PKTCOUNTLO); // C18
173 Reserved.set(Hexagon::PKTCOUNTHI); // C19
174 Reserved.set(Hexagon::UTIMERLO); // C30
175 Reserved.set(Hexagon::UTIMERHI); // C31
176 // Out of the control registers, only C8 is explicitly defined in
177 // HexagonRegisterInfo.td. If others are defined, make sure to add
178 // them here as well.
179 Reserved.set(Hexagon::C8);
180 Reserved.set(Hexagon::USR_OVF);
181
182 // Leveraging these registers will require more work to recognize
183 // the new semantics posed, Hi/LoVec patterns, etc.
184 // Note well: if enabled, they should be restricted to only
185 // where `HST.useHVXOps() && HST.hasV67Ops()` is true.
186 for (auto Reg : Hexagon_MC::GetVectRegRev())
187 Reserved.set(Reg);
188
190 Reserved.set(Hexagon::R19);
191
192 Register AP =
193 MF.getInfo<HexagonMachineFunctionInfo>()->getStackAlignBaseReg();
194 if (AP.isValid())
195 Reserved.set(AP);
196
197 for (int x = Reserved.find_first(); x >= 0; x = Reserved.find_next(x))
198 markSuperRegs(Reserved, x);
199
200 return Reserved;
201}
202
204 int SPAdj, unsigned FIOp,
205 RegScavenger *RS) const {
206 static unsigned ReuseCount = 0;
207 //
208 // Hexagon_TODO: Do we need to enforce this for Hexagon?
209 assert(SPAdj == 0 && "Unexpected");
210
211 MachineInstr &MI = *II;
212 MachineBasicBlock &MB = *MI.getParent();
213 MachineFunction &MF = *MB.getParent();
214 auto &HST = MF.getSubtarget<HexagonSubtarget>();
215 auto &HII = *HST.getInstrInfo();
216 auto &HFI = *HST.getFrameLowering();
217
218 Register BP;
219 int FI = MI.getOperand(FIOp).getIndex();
220 // Select the base pointer (BP) and calculate the actual offset from BP
221 // to the beginning of the object at index FI.
222 int Offset = HFI.getFrameIndexReference(MF, FI, BP).getFixed();
223 // Add the offset from the instruction.
224 int RealOffset = Offset + MI.getOperand(FIOp+1).getImm();
225
226 unsigned Opc = MI.getOpcode();
227 switch (Opc) {
228 case Hexagon::PS_fia:
229 MI.setDesc(HII.get(Hexagon::A2_addi));
230 MI.getOperand(FIOp).ChangeToImmediate(RealOffset);
231 MI.removeOperand(FIOp+1);
232 return false;
233 case Hexagon::PS_fi:
234 // Set up the instruction for updating below.
235 MI.setDesc(HII.get(Hexagon::A2_addi));
236 break;
237 }
238
239 if (!HII.isValidOffset(Opc, RealOffset, this)) {
240 // If the offset is not valid, calculate the address in a temporary
241 // register and use it with offset 0.
242 int InstOffset = 0;
243 // The actual base register (BP) is typically shared between many
244 // instructions where frame indices are being replaced. In scalar
245 // instructions the offset range is large, and the need for an extra
246 // add instruction is infrequent. Vector loads/stores, however, have
247 // a much smaller offset range: [-8, 7), or #s4. In those cases it
248 // makes sense to "standardize" the immediate in the "addi" instruction
249 // so that multiple loads/stores could be based on it.
250 bool IsPair = false;
251 switch (MI.getOpcode()) {
252 // All of these instructions have the same format: base+#s4.
253 case Hexagon::PS_vloadrw_ai:
254 case Hexagon::PS_vloadrw_nt_ai:
255 case Hexagon::PS_vstorerw_ai:
256 case Hexagon::PS_vstorerw_nt_ai:
257 IsPair = true;
258 [[fallthrough]];
259 case Hexagon::PS_vloadrv_ai:
260 case Hexagon::PS_vloadrv_nt_ai:
261 case Hexagon::PS_vstorerv_ai:
262 case Hexagon::PS_vstorerv_nt_ai:
263 case Hexagon::V6_vL32b_ai:
264 case Hexagon::V6_vS32b_ai: {
265 unsigned HwLen = HST.getVectorLength();
266 if (RealOffset % HwLen == 0) {
267 int VecOffset = RealOffset / HwLen;
268 // Rewrite the offset as "base + [-8, 7)".
269 VecOffset += 8;
270 // Pairs are expanded into two instructions: make sure that both
271 // can use the same base (i.e. VecOffset+1 is not a different
272 // multiple of 16 than VecOffset).
273 if (!IsPair || (VecOffset + 1) % 16 != 0) {
274 RealOffset = (VecOffset & -16) * HwLen;
275 InstOffset = (VecOffset % 16 - 8) * HwLen;
276 }
277 }
278 }
279 }
280
281 // Search backwards in the block for "Reg = A2_addi BP, RealOffset".
282 // This will give us a chance to avoid creating a new register.
283 Register ReuseBP;
284
285 if (ReuseCount < FrameIndexReuseLimit) {
286 unsigned SearchCount = 0, SearchRange = FrameIndexSearchRange;
287 SmallSet<Register,2> SeenVRegs;
288 bool PassedCall = false;
289 LiveRegUnits Defs(*this), Uses(*this);
290
291 for (auto I = std::next(II.getReverse()), E = MB.rend(); I != E; ++I) {
292 if (SearchCount == SearchRange)
293 break;
294 ++SearchCount;
295 const MachineInstr &BI = *I;
297 PassedCall |= BI.isCall();
298 for (const MachineOperand &Op : BI.operands()) {
299 if (SeenVRegs.size() > 1)
300 break;
301 if (Op.isReg() && Op.getReg().isVirtual())
302 SeenVRegs.insert(Op.getReg());
303 }
304 if (BI.getOpcode() != Hexagon::A2_addi)
305 continue;
306 if (BI.getOperand(1).getReg() != BP)
307 continue;
308 const auto &Op2 = BI.getOperand(2);
309 if (!Op2.isImm() || Op2.getImm() != RealOffset)
310 continue;
311
312 Register R = BI.getOperand(0).getReg();
313 if (R.isPhysical()) {
314 if (Defs.available(R))
315 ReuseBP = R;
316 } else if (R.isVirtual()) {
317 // Extending a range of a virtual register can be dangerous,
318 // since the scavenger will need to find a physical register
319 // for it. Avoid extending the range past a function call,
320 // and avoid overlapping it with another virtual register.
321 if (!PassedCall && SeenVRegs.size() <= 1)
322 ReuseBP = R;
323 }
324 break;
325 }
326 if (ReuseBP)
327 ++ReuseCount;
328 }
329
330 auto &MRI = MF.getRegInfo();
331 if (!ReuseBP) {
332 ReuseBP = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
333 const DebugLoc &DL = MI.getDebugLoc();
334 BuildMI(MB, II, DL, HII.get(Hexagon::A2_addi), ReuseBP)
335 .addReg(BP)
336 .addImm(RealOffset);
337 }
338 BP = ReuseBP;
339 RealOffset = InstOffset;
340 }
341
342 MI.getOperand(FIOp).ChangeToRegister(BP, false, false, false);
343 MI.getOperand(FIOp+1).ChangeToImmediate(RealOffset);
344 return false;
345}
346
347
349 const TargetRegisterClass *SrcRC, unsigned SubReg,
350 const TargetRegisterClass *DstRC, unsigned DstSubReg,
351 const TargetRegisterClass *NewRC, LiveIntervals &LIS) const {
352 // Coalescing will extend the live interval of the destination register.
353 // If the destination register is a vector pair, avoid introducing function
354 // calls into the interval, since it could result in a spilling of a pair
355 // instead of a single vector.
356 MachineFunction &MF = *MI->getParent()->getParent();
358 if (!HST.useHVXOps() || NewRC->getID() != Hexagon::HvxWRRegClass.getID())
359 return true;
360 bool SmallSrc = SrcRC->getID() == Hexagon::HvxVRRegClass.getID();
361 bool SmallDst = DstRC->getID() == Hexagon::HvxVRRegClass.getID();
362 if (!SmallSrc && !SmallDst)
363 return true;
364
365 Register DstReg = MI->getOperand(0).getReg();
366 Register SrcReg = MI->getOperand(1).getReg();
367 const SlotIndexes &Indexes = *LIS.getSlotIndexes();
368 auto HasCall = [&Indexes] (const LiveInterval::Segment &S) {
369 for (SlotIndex I = S.start.getBaseIndex(), E = S.end.getBaseIndex();
370 I != E; I = I.getNextIndex()) {
371 if (const MachineInstr *MI = Indexes.getInstructionFromIndex(I))
372 if (MI->isCall())
373 return true;
374 }
375 return false;
376 };
377
378 if (SmallSrc == SmallDst) {
379 // Both must be true, because the case for both being false was
380 // checked earlier. Both registers will be coalesced into a register
381 // of a wider class (HvxWR), and we don't want its live range to
382 // span over calls.
383 return !any_of(LIS.getInterval(DstReg), HasCall) &&
384 !any_of(LIS.getInterval(SrcReg), HasCall);
385 }
386
387 // If one register is large (HvxWR) and the other is small (HvxVR), then
388 // coalescing is ok if the large is already live across a function call,
389 // or if the small one is not.
390 Register SmallReg = SmallSrc ? SrcReg : DstReg;
391 Register LargeReg = SmallSrc ? DstReg : SrcReg;
392 return any_of(LIS.getInterval(LargeReg), HasCall) ||
393 !any_of(LIS.getInterval(SmallReg), HasCall);
394}
395
396
398 &MF) const {
399 const HexagonFrameLowering *TFI = getFrameLowering(MF);
400 if (TFI->hasFP(MF))
401 return getFrameRegister();
402 return getStackRegister();
403}
404
405
407 return Hexagon::R30;
408}
409
410
412 return Hexagon::R29;
413}
414
415
417 const TargetRegisterClass &RC, unsigned GenIdx) const {
418 assert(GenIdx == Hexagon::ps_sub_lo || GenIdx == Hexagon::ps_sub_hi);
419
420 static const unsigned ISub[] = { Hexagon::isub_lo, Hexagon::isub_hi };
421 static const unsigned VSub[] = { Hexagon::vsub_lo, Hexagon::vsub_hi };
422 static const unsigned WSub[] = { Hexagon::wsub_lo, Hexagon::wsub_hi };
423
424 switch (RC.getID()) {
425 case Hexagon::CtrRegs64RegClassID:
426 case Hexagon::DoubleRegsRegClassID:
427 return ISub[GenIdx];
428 case Hexagon::HvxWRRegClassID:
429 return VSub[GenIdx];
430 case Hexagon::HvxVQRRegClassID:
431 return WSub[GenIdx];
432 }
433
434 if (!RC.superclasses().empty())
436 GenIdx);
437
438 llvm_unreachable("Invalid register class");
439}
440
442 const {
443 return MF.getSubtarget<HexagonSubtarget>().getFrameLowering()->hasFP(MF);
444}
445
448 return &Hexagon::IntRegsRegClass;
449}
unsigned SubReg
unsigned const MachineRegisterInfo * MRI
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file implements the BitVector class.
static cl::opt< unsigned > FrameIndexReuseLimit("hexagon-frame-index-reuse-limit", cl::init(~0), cl::Hidden, cl::desc("Limit on the number of reused registers in frame index " "elimination"))
static cl::opt< unsigned > FrameIndexSearchRange("hexagon-frame-index-search-range", cl::init(32), cl::Hidden, cl::desc("Limit on instruction search range in frame index elimination"))
IRTranslator LLVM IR MI
A set of register units.
#define I(x, y, z)
Definition MD5.cpp:58
#define R4(n)
#define R2(n)
#define R6(n)
uint64_t IntrinsicInst * II
This file declares the machine register scavenger class.
Remove Loads Into Fake Uses
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallSet class.
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
iterator begin() const
Definition ArrayRef.h:135
bool empty() const
empty - Check if the array is empty.
Definition ArrayRef.h:142
A debug info location.
Definition DebugLoc.h:124
Hexagon target-specific information for each MachineFunction.
bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=nullptr) const override
bool isEHReturnCalleeSaveReg(Register Reg) const
BitVector getReservedRegs(const MachineFunction &MF) const override
const TargetRegisterClass * getPointerRegClass(unsigned Kind=0) const override
bool useFPForScavengingIndex(const MachineFunction &MF) const override
Returns true if the frame pointer is valid.
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
unsigned getHexagonSubRegIndex(const TargetRegisterClass &RC, unsigned GenIdx) const
bool shouldCoalesce(MachineInstr *MI, const TargetRegisterClass *SrcRC, unsigned SubReg, const TargetRegisterClass *DstRC, unsigned DstSubReg, const TargetRegisterClass *NewRC, LiveIntervals &LIS) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
const MCPhysReg * getCallerSavedRegs(const MachineFunction *MF, const TargetRegisterClass *RC) const
const HexagonInstrInfo * getInstrInfo() const override
SlotIndexes * getSlotIndexes() const
LiveInterval & getInterval(Register Reg)
A set of register units used to track register liveness.
static void accumulateUsedDefed(const MachineInstr &MI, LiveRegUnits &ModifiedRegUnits, LiveRegUnits &UsedRegUnits, const TargetRegisterInfo *TRI)
For a machine instruction MI, adds all register units used in UsedRegUnits and defined or clobbered i...
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool isCall(QueryType Type=AnyInBundle) const
mop_range operands()
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
Wrapper class representing virtual and physical registers.
Definition Register.h:19
constexpr bool isValid() const
Definition Register.h:107
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:66
SlotIndexes pass.
MachineInstr * getInstructionFromIndex(SlotIndex index) const
Returns the instruction for the given index, or null if the given index has no instruction associated...
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:133
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:181
size_type size() const
Definition SmallSet.h:170
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
unsigned getID() const
Return the register class ID number.
ArrayRef< unsigned > superclasses() const
Returns a list of super-classes.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
llvm::ArrayRef< MCPhysReg > GetVectRegRev()
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1721
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
DWARFExpression::Operation Op
This represents a simple continuous liveness interval for a value.