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