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