xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
10b57cec5SDimitry Andric //===-- HexagonRegisterInfo.cpp - Hexagon Register Information ------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains the Hexagon implementation of the TargetRegisterInfo
100b57cec5SDimitry Andric // class.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "HexagonRegisterInfo.h"
150b57cec5SDimitry Andric #include "Hexagon.h"
160b57cec5SDimitry Andric #include "HexagonMachineFunctionInfo.h"
170b57cec5SDimitry Andric #include "HexagonSubtarget.h"
180b57cec5SDimitry Andric #include "HexagonTargetMachine.h"
190b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
20*fe6060f1SDimitry Andric #include "llvm/ADT/SmallSet.h"
210b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
23*fe6060f1SDimitry Andric #include "llvm/CodeGen/LiveRegUnits.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/PseudoSourceValue.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
320b57cec5SDimitry Andric #include "llvm/IR/Function.h"
330b57cec5SDimitry Andric #include "llvm/IR/Type.h"
340b57cec5SDimitry Andric #include "llvm/MC/MachineLocation.h"
35*fe6060f1SDimitry Andric #include "llvm/Support/CommandLine.h"
360b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
370b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
380b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
390b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
400b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h"
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric #define GET_REGINFO_TARGET_DESC
430b57cec5SDimitry Andric #include "HexagonGenRegisterInfo.inc"
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric using namespace llvm;
460b57cec5SDimitry Andric 
47*fe6060f1SDimitry Andric static cl::opt<unsigned> FrameIndexSearchRange(
48*fe6060f1SDimitry Andric     "hexagon-frame-index-search-range", cl::init(32), cl::Hidden,
49*fe6060f1SDimitry Andric     cl::desc("Limit on instruction search range in frame index elimination"));
50*fe6060f1SDimitry Andric 
51*fe6060f1SDimitry Andric static cl::opt<unsigned> FrameIndexReuseLimit(
52*fe6060f1SDimitry Andric     "hexagon-frame-index-reuse-limit", cl::init(~0), cl::Hidden,
53*fe6060f1SDimitry Andric     cl::desc("Limit on the number of reused registers in frame index "
54*fe6060f1SDimitry Andric     "elimination"));
55*fe6060f1SDimitry Andric 
560b57cec5SDimitry Andric HexagonRegisterInfo::HexagonRegisterInfo(unsigned HwMode)
570b57cec5SDimitry Andric     : HexagonGenRegisterInfo(Hexagon::R31, 0/*DwarfFlavor*/, 0/*EHFlavor*/,
580b57cec5SDimitry Andric                              0/*PC*/, HwMode) {}
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric bool HexagonRegisterInfo::isEHReturnCalleeSaveReg(unsigned R) const {
620b57cec5SDimitry Andric   return R == Hexagon::R0 || R == Hexagon::R1 || R == Hexagon::R2 ||
630b57cec5SDimitry Andric          R == Hexagon::R3 || R == Hexagon::D0 || R == Hexagon::D1;
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric const MCPhysReg *
670b57cec5SDimitry Andric HexagonRegisterInfo::getCallerSavedRegs(const MachineFunction *MF,
680b57cec5SDimitry Andric       const TargetRegisterClass *RC) const {
690b57cec5SDimitry Andric   using namespace Hexagon;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   static const MCPhysReg Int32[] = {
720b57cec5SDimitry Andric     R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, 0
730b57cec5SDimitry Andric   };
740b57cec5SDimitry Andric   static const MCPhysReg Int64[] = {
750b57cec5SDimitry Andric     D0, D1, D2, D3, D4, D5, D6, D7, 0
760b57cec5SDimitry Andric   };
770b57cec5SDimitry Andric   static const MCPhysReg Pred[] = {
780b57cec5SDimitry Andric     P0, P1, P2, P3, 0
790b57cec5SDimitry Andric   };
800b57cec5SDimitry Andric   static const MCPhysReg VecSgl[] = {
810b57cec5SDimitry Andric      V0,  V1,  V2,  V3,  V4,  V5,  V6,  V7,  V8,  V9, V10, V11, V12, V13,
820b57cec5SDimitry Andric     V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27,
830b57cec5SDimitry Andric     V28, V29, V30, V31,   0
840b57cec5SDimitry Andric   };
850b57cec5SDimitry Andric   static const MCPhysReg VecDbl[] = {
860b57cec5SDimitry Andric     W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, 0
870b57cec5SDimitry Andric   };
88480093f4SDimitry Andric   static const MCPhysReg VecPred[] = {
89480093f4SDimitry Andric     Q0, Q1, Q2, Q3, 0
90480093f4SDimitry Andric   };
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   switch (RC->getID()) {
930b57cec5SDimitry Andric     case IntRegsRegClassID:
940b57cec5SDimitry Andric       return Int32;
950b57cec5SDimitry Andric     case DoubleRegsRegClassID:
960b57cec5SDimitry Andric       return Int64;
970b57cec5SDimitry Andric     case PredRegsRegClassID:
980b57cec5SDimitry Andric       return Pred;
990b57cec5SDimitry Andric     case HvxVRRegClassID:
1000b57cec5SDimitry Andric       return VecSgl;
1010b57cec5SDimitry Andric     case HvxWRRegClassID:
1020b57cec5SDimitry Andric       return VecDbl;
103480093f4SDimitry Andric     case HvxQRRegClassID:
104480093f4SDimitry Andric       return VecPred;
1050b57cec5SDimitry Andric     default:
1060b57cec5SDimitry Andric       break;
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   static const MCPhysReg Empty[] = { 0 };
1100b57cec5SDimitry Andric #ifndef NDEBUG
1110b57cec5SDimitry Andric   dbgs() << "Register class: " << getRegClassName(RC) << "\n";
1120b57cec5SDimitry Andric #endif
1130b57cec5SDimitry Andric   llvm_unreachable("Unexpected register class");
1140b57cec5SDimitry Andric   return Empty;
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric const MCPhysReg *
1190b57cec5SDimitry Andric HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
1200b57cec5SDimitry Andric   static const MCPhysReg CalleeSavedRegsV3[] = {
1210b57cec5SDimitry Andric     Hexagon::R16,   Hexagon::R17,   Hexagon::R18,   Hexagon::R19,
1220b57cec5SDimitry Andric     Hexagon::R20,   Hexagon::R21,   Hexagon::R22,   Hexagon::R23,
1230b57cec5SDimitry Andric     Hexagon::R24,   Hexagon::R25,   Hexagon::R26,   Hexagon::R27, 0
1240b57cec5SDimitry Andric   };
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   // Functions that contain a call to __builtin_eh_return also save the first 4
1270b57cec5SDimitry Andric   // parameter registers.
1280b57cec5SDimitry Andric   static const MCPhysReg CalleeSavedRegsV3EHReturn[] = {
1290b57cec5SDimitry Andric     Hexagon::R0,    Hexagon::R1,    Hexagon::R2,    Hexagon::R3,
1300b57cec5SDimitry Andric     Hexagon::R16,   Hexagon::R17,   Hexagon::R18,   Hexagon::R19,
1310b57cec5SDimitry Andric     Hexagon::R20,   Hexagon::R21,   Hexagon::R22,   Hexagon::R23,
1320b57cec5SDimitry Andric     Hexagon::R24,   Hexagon::R25,   Hexagon::R26,   Hexagon::R27, 0
1330b57cec5SDimitry Andric   };
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   bool HasEHReturn = MF->getInfo<HexagonMachineFunctionInfo>()->hasEHReturn();
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   return HasEHReturn ? CalleeSavedRegsV3EHReturn : CalleeSavedRegsV3;
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric const uint32_t *HexagonRegisterInfo::getCallPreservedMask(
1420b57cec5SDimitry Andric       const MachineFunction &MF, CallingConv::ID) const {
1430b57cec5SDimitry Andric   return HexagonCSR_RegMask;
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
1480b57cec5SDimitry Andric       const {
1490b57cec5SDimitry Andric   BitVector Reserved(getNumRegs());
1500b57cec5SDimitry Andric   Reserved.set(Hexagon::R29);
1510b57cec5SDimitry Andric   Reserved.set(Hexagon::R30);
1520b57cec5SDimitry Andric   Reserved.set(Hexagon::R31);
1530b57cec5SDimitry Andric   Reserved.set(Hexagon::VTMP);
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   // Guest registers.
1560b57cec5SDimitry Andric   Reserved.set(Hexagon::GELR);        // G0
1570b57cec5SDimitry Andric   Reserved.set(Hexagon::GSR);         // G1
1580b57cec5SDimitry Andric   Reserved.set(Hexagon::GOSP);        // G2
1590b57cec5SDimitry Andric   Reserved.set(Hexagon::G3);          // G3
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   // Control registers.
1620b57cec5SDimitry Andric   Reserved.set(Hexagon::SA0);         // C0
1630b57cec5SDimitry Andric   Reserved.set(Hexagon::LC0);         // C1
1640b57cec5SDimitry Andric   Reserved.set(Hexagon::SA1);         // C2
1650b57cec5SDimitry Andric   Reserved.set(Hexagon::LC1);         // C3
1660b57cec5SDimitry Andric   Reserved.set(Hexagon::P3_0);        // C4
1670b57cec5SDimitry Andric   Reserved.set(Hexagon::USR);         // C8
1680b57cec5SDimitry Andric   Reserved.set(Hexagon::PC);          // C9
1690b57cec5SDimitry Andric   Reserved.set(Hexagon::UGP);         // C10
1700b57cec5SDimitry Andric   Reserved.set(Hexagon::GP);          // C11
1710b57cec5SDimitry Andric   Reserved.set(Hexagon::CS0);         // C12
1720b57cec5SDimitry Andric   Reserved.set(Hexagon::CS1);         // C13
1730b57cec5SDimitry Andric   Reserved.set(Hexagon::UPCYCLELO);   // C14
1740b57cec5SDimitry Andric   Reserved.set(Hexagon::UPCYCLEHI);   // C15
1750b57cec5SDimitry Andric   Reserved.set(Hexagon::FRAMELIMIT);  // C16
1760b57cec5SDimitry Andric   Reserved.set(Hexagon::FRAMEKEY);    // C17
1770b57cec5SDimitry Andric   Reserved.set(Hexagon::PKTCOUNTLO);  // C18
1780b57cec5SDimitry Andric   Reserved.set(Hexagon::PKTCOUNTHI);  // C19
1790b57cec5SDimitry Andric   Reserved.set(Hexagon::UTIMERLO);    // C30
1800b57cec5SDimitry Andric   Reserved.set(Hexagon::UTIMERHI);    // C31
1810b57cec5SDimitry Andric   // Out of the control registers, only C8 is explicitly defined in
1820b57cec5SDimitry Andric   // HexagonRegisterInfo.td. If others are defined, make sure to add
1830b57cec5SDimitry Andric   // them here as well.
1840b57cec5SDimitry Andric   Reserved.set(Hexagon::C8);
1850b57cec5SDimitry Andric   Reserved.set(Hexagon::USR_OVF);
1860b57cec5SDimitry Andric 
1875ffd83dbSDimitry Andric   // Leveraging these registers will require more work to recognize
1885ffd83dbSDimitry Andric   // the new semantics posed, Hi/LoVec patterns, etc.
1895ffd83dbSDimitry Andric   // Note well: if enabled, they should be restricted to only
1905ffd83dbSDimitry Andric   // where `HST.useHVXOps() && HST.hasV67Ops()` is true.
1915ffd83dbSDimitry Andric   for (auto Reg : Hexagon_MC::GetVectRegRev())
1925ffd83dbSDimitry Andric     Reserved.set(Reg);
1935ffd83dbSDimitry Andric 
1940b57cec5SDimitry Andric   if (MF.getSubtarget<HexagonSubtarget>().hasReservedR19())
1950b57cec5SDimitry Andric     Reserved.set(Hexagon::R19);
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   for (int x = Reserved.find_first(); x >= 0; x = Reserved.find_next(x))
1980b57cec5SDimitry Andric     markSuperRegs(Reserved, x);
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   return Reserved;
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
2040b57cec5SDimitry Andric                                               int SPAdj, unsigned FIOp,
2050b57cec5SDimitry Andric                                               RegScavenger *RS) const {
206*fe6060f1SDimitry Andric   static unsigned ReuseCount = 0;
2070b57cec5SDimitry Andric   //
2080b57cec5SDimitry Andric   // Hexagon_TODO: Do we need to enforce this for Hexagon?
2090b57cec5SDimitry Andric   assert(SPAdj == 0 && "Unexpected");
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   MachineInstr &MI = *II;
2120b57cec5SDimitry Andric   MachineBasicBlock &MB = *MI.getParent();
2130b57cec5SDimitry Andric   MachineFunction &MF = *MB.getParent();
2140b57cec5SDimitry Andric   auto &HST = MF.getSubtarget<HexagonSubtarget>();
2150b57cec5SDimitry Andric   auto &HII = *HST.getInstrInfo();
2160b57cec5SDimitry Andric   auto &HFI = *HST.getFrameLowering();
2170b57cec5SDimitry Andric 
2185ffd83dbSDimitry Andric   Register BP;
2190b57cec5SDimitry Andric   int FI = MI.getOperand(FIOp).getIndex();
2200b57cec5SDimitry Andric   // Select the base pointer (BP) and calculate the actual offset from BP
2210b57cec5SDimitry Andric   // to the beginning of the object at index FI.
222e8d8bef9SDimitry Andric   int Offset = HFI.getFrameIndexReference(MF, FI, BP).getFixed();
2230b57cec5SDimitry Andric   // Add the offset from the instruction.
2240b57cec5SDimitry Andric   int RealOffset = Offset + MI.getOperand(FIOp+1).getImm();
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
2270b57cec5SDimitry Andric   switch (Opc) {
2280b57cec5SDimitry Andric     case Hexagon::PS_fia:
2290b57cec5SDimitry Andric       MI.setDesc(HII.get(Hexagon::A2_addi));
2300b57cec5SDimitry Andric       MI.getOperand(FIOp).ChangeToImmediate(RealOffset);
2310b57cec5SDimitry Andric       MI.RemoveOperand(FIOp+1);
2320b57cec5SDimitry Andric       return;
2330b57cec5SDimitry Andric     case Hexagon::PS_fi:
2340b57cec5SDimitry Andric       // Set up the instruction for updating below.
2350b57cec5SDimitry Andric       MI.setDesc(HII.get(Hexagon::A2_addi));
2360b57cec5SDimitry Andric       break;
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   if (!HII.isValidOffset(Opc, RealOffset, this)) {
2400b57cec5SDimitry Andric     // If the offset is not valid, calculate the address in a temporary
2410b57cec5SDimitry Andric     // register and use it with offset 0.
242*fe6060f1SDimitry Andric     int InstOffset = 0;
243*fe6060f1SDimitry Andric     // The actual base register (BP) is typically shared between many
244*fe6060f1SDimitry Andric     // instructions where frame indices are being replaced. In scalar
245*fe6060f1SDimitry Andric     // instructions the offset range is large, and the need for an extra
246*fe6060f1SDimitry Andric     // add instruction is infrequent. Vector loads/stores, however, have
247*fe6060f1SDimitry Andric     // a much smaller offset range: [-8, 7), or #s4. In those cases it
248*fe6060f1SDimitry Andric     // makes sense to "standardize" the immediate in the "addi" instruction
249*fe6060f1SDimitry Andric     // so that multiple loads/stores could be based on it.
250*fe6060f1SDimitry Andric     bool IsPair = false;
251*fe6060f1SDimitry Andric     switch (MI.getOpcode()) {
252*fe6060f1SDimitry Andric       // All of these instructions have the same format: base+#s4.
253*fe6060f1SDimitry Andric       case Hexagon::PS_vloadrw_ai:
254*fe6060f1SDimitry Andric       case Hexagon::PS_vloadrw_nt_ai:
255*fe6060f1SDimitry Andric       case Hexagon::PS_vstorerw_ai:
256*fe6060f1SDimitry Andric       case Hexagon::PS_vstorerw_nt_ai:
257*fe6060f1SDimitry Andric         IsPair = true;
258*fe6060f1SDimitry Andric         LLVM_FALLTHROUGH;
259*fe6060f1SDimitry Andric       case Hexagon::PS_vloadrv_ai:
260*fe6060f1SDimitry Andric       case Hexagon::PS_vloadrv_nt_ai:
261*fe6060f1SDimitry Andric       case Hexagon::PS_vstorerv_ai:
262*fe6060f1SDimitry Andric       case Hexagon::PS_vstorerv_nt_ai:
263*fe6060f1SDimitry Andric       case Hexagon::V6_vL32b_ai:
264*fe6060f1SDimitry Andric       case Hexagon::V6_vS32b_ai: {
265*fe6060f1SDimitry Andric         unsigned HwLen = HST.getVectorLength();
266*fe6060f1SDimitry Andric         if (RealOffset % HwLen == 0) {
267*fe6060f1SDimitry Andric           int VecOffset = RealOffset / HwLen;
268*fe6060f1SDimitry Andric           // Rewrite the offset as "base + [-8, 7)".
269*fe6060f1SDimitry Andric           VecOffset += 8;
270*fe6060f1SDimitry Andric           // Pairs are expanded into two instructions: make sure that both
271*fe6060f1SDimitry Andric           // can use the same base (i.e. VecOffset+1 is not a different
272*fe6060f1SDimitry Andric           // multiple of 16 than VecOffset).
273*fe6060f1SDimitry Andric           if (!IsPair || (VecOffset + 1) % 16 != 0) {
274*fe6060f1SDimitry Andric             RealOffset = (VecOffset & -16) * HwLen;
275*fe6060f1SDimitry Andric             InstOffset = (VecOffset % 16 - 8) * HwLen;
276*fe6060f1SDimitry Andric           }
277*fe6060f1SDimitry Andric         }
278*fe6060f1SDimitry Andric       }
2790b57cec5SDimitry Andric     }
2800b57cec5SDimitry Andric 
281*fe6060f1SDimitry Andric     // Search backwards in the block for "Reg = A2_addi BP, RealOffset".
282*fe6060f1SDimitry Andric     // This will give us a chance to avoid creating a new register.
283*fe6060f1SDimitry Andric     Register ReuseBP;
284*fe6060f1SDimitry Andric 
285*fe6060f1SDimitry Andric     if (ReuseCount < FrameIndexReuseLimit) {
286*fe6060f1SDimitry Andric       unsigned SearchCount = 0, SearchRange = FrameIndexSearchRange;
287*fe6060f1SDimitry Andric       SmallSet<Register,2> SeenVRegs;
288*fe6060f1SDimitry Andric       bool PassedCall = false;
289*fe6060f1SDimitry Andric       LiveRegUnits Defs(*this), Uses(*this);
290*fe6060f1SDimitry Andric 
291*fe6060f1SDimitry Andric       for (auto I = std::next(II.getReverse()), E = MB.rend(); I != E; ++I) {
292*fe6060f1SDimitry Andric         if (SearchCount == SearchRange)
293*fe6060f1SDimitry Andric           break;
294*fe6060f1SDimitry Andric         ++SearchCount;
295*fe6060f1SDimitry Andric         const MachineInstr &BI = *I;
296*fe6060f1SDimitry Andric         LiveRegUnits::accumulateUsedDefed(BI, Defs, Uses, this);
297*fe6060f1SDimitry Andric         PassedCall |= BI.isCall();
298*fe6060f1SDimitry Andric         for (const MachineOperand &Op : BI.operands()) {
299*fe6060f1SDimitry Andric           if (SeenVRegs.size() > 1)
300*fe6060f1SDimitry Andric             break;
301*fe6060f1SDimitry Andric           if (Op.isReg() && Op.getReg().isVirtual())
302*fe6060f1SDimitry Andric             SeenVRegs.insert(Op.getReg());
303*fe6060f1SDimitry Andric         }
304*fe6060f1SDimitry Andric         if (BI.getOpcode() != Hexagon::A2_addi)
305*fe6060f1SDimitry Andric           continue;
306*fe6060f1SDimitry Andric         if (BI.getOperand(1).getReg() != BP)
307*fe6060f1SDimitry Andric           continue;
308*fe6060f1SDimitry Andric         const auto &Op2 = BI.getOperand(2);
309*fe6060f1SDimitry Andric         if (!Op2.isImm() || Op2.getImm() != RealOffset)
310*fe6060f1SDimitry Andric           continue;
311*fe6060f1SDimitry Andric 
312*fe6060f1SDimitry Andric         Register R = BI.getOperand(0).getReg();
313*fe6060f1SDimitry Andric         if (R.isPhysical()) {
314*fe6060f1SDimitry Andric           if (Defs.available(R))
315*fe6060f1SDimitry Andric             ReuseBP = R;
316*fe6060f1SDimitry Andric         } else if (R.isVirtual()) {
317*fe6060f1SDimitry Andric           // Extending a range of a virtual register can be dangerous,
318*fe6060f1SDimitry Andric           // since the scavenger will need to find a physical register
319*fe6060f1SDimitry Andric           // for it. Avoid extending the range past a function call,
320*fe6060f1SDimitry Andric           // and avoid overlapping it with another virtual register.
321*fe6060f1SDimitry Andric           if (!PassedCall && SeenVRegs.size() <= 1)
322*fe6060f1SDimitry Andric             ReuseBP = R;
323*fe6060f1SDimitry Andric         }
324*fe6060f1SDimitry Andric         break;
325*fe6060f1SDimitry Andric       }
326*fe6060f1SDimitry Andric       if (ReuseBP)
327*fe6060f1SDimitry Andric         ++ReuseCount;
328*fe6060f1SDimitry Andric     }
329*fe6060f1SDimitry Andric 
330*fe6060f1SDimitry Andric     auto &MRI = MF.getRegInfo();
331*fe6060f1SDimitry Andric     if (!ReuseBP) {
332*fe6060f1SDimitry Andric       ReuseBP = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
333*fe6060f1SDimitry Andric       const DebugLoc &DL = MI.getDebugLoc();
334*fe6060f1SDimitry Andric       BuildMI(MB, II, DL, HII.get(Hexagon::A2_addi), ReuseBP)
335*fe6060f1SDimitry Andric         .addReg(BP)
336*fe6060f1SDimitry Andric         .addImm(RealOffset);
337*fe6060f1SDimitry Andric     }
338*fe6060f1SDimitry Andric     BP = ReuseBP;
339*fe6060f1SDimitry Andric     RealOffset = InstOffset;
340*fe6060f1SDimitry Andric   }
341*fe6060f1SDimitry Andric 
342*fe6060f1SDimitry Andric   MI.getOperand(FIOp).ChangeToRegister(BP, false, false, false);
3430b57cec5SDimitry Andric   MI.getOperand(FIOp+1).ChangeToImmediate(RealOffset);
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric bool HexagonRegisterInfo::shouldCoalesce(MachineInstr *MI,
3480b57cec5SDimitry Andric       const TargetRegisterClass *SrcRC, unsigned SubReg,
3490b57cec5SDimitry Andric       const TargetRegisterClass *DstRC, unsigned DstSubReg,
3500b57cec5SDimitry Andric       const TargetRegisterClass *NewRC, LiveIntervals &LIS) const {
3510b57cec5SDimitry Andric   // Coalescing will extend the live interval of the destination register.
3520b57cec5SDimitry Andric   // If the destination register is a vector pair, avoid introducing function
3530b57cec5SDimitry Andric   // calls into the interval, since it could result in a spilling of a pair
3540b57cec5SDimitry Andric   // instead of a single vector.
3550b57cec5SDimitry Andric   MachineFunction &MF = *MI->getParent()->getParent();
3560b57cec5SDimitry Andric   const HexagonSubtarget &HST = MF.getSubtarget<HexagonSubtarget>();
3570b57cec5SDimitry Andric   if (!HST.useHVXOps() || NewRC->getID() != Hexagon::HvxWRRegClass.getID())
3580b57cec5SDimitry Andric     return true;
3590b57cec5SDimitry Andric   bool SmallSrc = SrcRC->getID() == Hexagon::HvxVRRegClass.getID();
3600b57cec5SDimitry Andric   bool SmallDst = DstRC->getID() == Hexagon::HvxVRRegClass.getID();
3610b57cec5SDimitry Andric   if (!SmallSrc && !SmallDst)
3620b57cec5SDimitry Andric     return true;
3630b57cec5SDimitry Andric 
3648bcb0991SDimitry Andric   Register DstReg = MI->getOperand(0).getReg();
3658bcb0991SDimitry Andric   Register SrcReg = MI->getOperand(1).getReg();
3660b57cec5SDimitry Andric   const SlotIndexes &Indexes = *LIS.getSlotIndexes();
3670b57cec5SDimitry Andric   auto HasCall = [&Indexes] (const LiveInterval::Segment &S) {
3680b57cec5SDimitry Andric     for (SlotIndex I = S.start.getBaseIndex(), E = S.end.getBaseIndex();
3690b57cec5SDimitry Andric          I != E; I = I.getNextIndex()) {
3700b57cec5SDimitry Andric       if (const MachineInstr *MI = Indexes.getInstructionFromIndex(I))
3710b57cec5SDimitry Andric         if (MI->isCall())
3720b57cec5SDimitry Andric           return true;
3730b57cec5SDimitry Andric     }
3740b57cec5SDimitry Andric     return false;
3750b57cec5SDimitry Andric   };
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   if (SmallSrc == SmallDst) {
3780b57cec5SDimitry Andric     // Both must be true, because the case for both being false was
3790b57cec5SDimitry Andric     // checked earlier. Both registers will be coalesced into a register
3800b57cec5SDimitry Andric     // of a wider class (HvxWR), and we don't want its live range to
3810b57cec5SDimitry Andric     // span over calls.
3820b57cec5SDimitry Andric     return !any_of(LIS.getInterval(DstReg), HasCall) &&
3830b57cec5SDimitry Andric            !any_of(LIS.getInterval(SrcReg), HasCall);
3840b57cec5SDimitry Andric   }
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   // If one register is large (HvxWR) and the other is small (HvxVR), then
3870b57cec5SDimitry Andric   // coalescing is ok if the large is already live across a function call,
3880b57cec5SDimitry Andric   // or if the small one is not.
3890b57cec5SDimitry Andric   unsigned SmallReg = SmallSrc ? SrcReg : DstReg;
3900b57cec5SDimitry Andric   unsigned LargeReg = SmallSrc ? DstReg : SrcReg;
3910b57cec5SDimitry Andric   return  any_of(LIS.getInterval(LargeReg), HasCall) ||
3920b57cec5SDimitry Andric          !any_of(LIS.getInterval(SmallReg), HasCall);
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric unsigned HexagonRegisterInfo::getRARegister() const {
3970b57cec5SDimitry Andric   return Hexagon::R31;
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric Register HexagonRegisterInfo::getFrameRegister(const MachineFunction
4020b57cec5SDimitry Andric                                                &MF) const {
4030b57cec5SDimitry Andric   const HexagonFrameLowering *TFI = getFrameLowering(MF);
4040b57cec5SDimitry Andric   if (TFI->hasFP(MF))
4050b57cec5SDimitry Andric     return getFrameRegister();
4060b57cec5SDimitry Andric   return getStackRegister();
4070b57cec5SDimitry Andric }
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric unsigned HexagonRegisterInfo::getFrameRegister() const {
4110b57cec5SDimitry Andric   return Hexagon::R30;
4120b57cec5SDimitry Andric }
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric unsigned HexagonRegisterInfo::getStackRegister() const {
4160b57cec5SDimitry Andric   return Hexagon::R29;
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric unsigned HexagonRegisterInfo::getHexagonSubRegIndex(
4210b57cec5SDimitry Andric       const TargetRegisterClass &RC, unsigned GenIdx) const {
4220b57cec5SDimitry Andric   assert(GenIdx == Hexagon::ps_sub_lo || GenIdx == Hexagon::ps_sub_hi);
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   static const unsigned ISub[] = { Hexagon::isub_lo, Hexagon::isub_hi };
4250b57cec5SDimitry Andric   static const unsigned VSub[] = { Hexagon::vsub_lo, Hexagon::vsub_hi };
4260b57cec5SDimitry Andric   static const unsigned WSub[] = { Hexagon::wsub_lo, Hexagon::wsub_hi };
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric   switch (RC.getID()) {
4290b57cec5SDimitry Andric     case Hexagon::CtrRegs64RegClassID:
4300b57cec5SDimitry Andric     case Hexagon::DoubleRegsRegClassID:
4310b57cec5SDimitry Andric       return ISub[GenIdx];
4320b57cec5SDimitry Andric     case Hexagon::HvxWRRegClassID:
4330b57cec5SDimitry Andric       return VSub[GenIdx];
4340b57cec5SDimitry Andric     case Hexagon::HvxVQRRegClassID:
4350b57cec5SDimitry Andric       return WSub[GenIdx];
4360b57cec5SDimitry Andric   }
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric   if (const TargetRegisterClass *SuperRC = *RC.getSuperClasses())
4390b57cec5SDimitry Andric     return getHexagonSubRegIndex(*SuperRC, GenIdx);
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric   llvm_unreachable("Invalid register class");
4420b57cec5SDimitry Andric }
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric bool HexagonRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF)
4450b57cec5SDimitry Andric       const {
4460b57cec5SDimitry Andric   return MF.getSubtarget<HexagonSubtarget>().getFrameLowering()->hasFP(MF);
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric const TargetRegisterClass *
4500b57cec5SDimitry Andric HexagonRegisterInfo::getPointerRegClass(const MachineFunction &MF,
4510b57cec5SDimitry Andric                                         unsigned Kind) const {
4520b57cec5SDimitry Andric   return &Hexagon::IntRegsRegClass;
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric unsigned HexagonRegisterInfo::getFirstCallerSavedNonParamReg() const {
4560b57cec5SDimitry Andric   return Hexagon::R6;
4570b57cec5SDimitry Andric }
4580b57cec5SDimitry Andric 
459