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"
20fe6060f1SDimitry Andric #include "llvm/ADT/SmallSet.h"
210b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
23fe6060f1SDimitry 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"
35fe6060f1SDimitry 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 
47fe6060f1SDimitry Andric static cl::opt<unsigned> FrameIndexSearchRange(
48fe6060f1SDimitry Andric     "hexagon-frame-index-search-range", cl::init(32), cl::Hidden,
49fe6060f1SDimitry Andric     cl::desc("Limit on instruction search range in frame index elimination"));
50fe6060f1SDimitry Andric 
51fe6060f1SDimitry Andric static cl::opt<unsigned> FrameIndexReuseLimit(
52fe6060f1SDimitry Andric     "hexagon-frame-index-reuse-limit", cl::init(~0), cl::Hidden,
53fe6060f1SDimitry Andric     cl::desc("Limit on the number of reused registers in frame index "
54fe6060f1SDimitry Andric     "elimination"));
55fe6060f1SDimitry Andric 
HexagonRegisterInfo(unsigned HwMode)560b57cec5SDimitry Andric HexagonRegisterInfo::HexagonRegisterInfo(unsigned HwMode)
570b57cec5SDimitry Andric     : HexagonGenRegisterInfo(Hexagon::R31, 0/*DwarfFlavor*/, 0/*EHFlavor*/,
580b57cec5SDimitry Andric                              0/*PC*/, HwMode) {}
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric 
isEHReturnCalleeSaveReg(Register R) const61bdd1243dSDimitry Andric bool HexagonRegisterInfo::isEHReturnCalleeSaveReg(Register 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 *
getCallerSavedRegs(const MachineFunction * MF,const TargetRegisterClass * RC) const670b57cec5SDimitry 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 *
getCalleeSavedRegs(const MachineFunction * MF) const1190b57cec5SDimitry 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 
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID) const1410b57cec5SDimitry 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 
getReservedRegs(const MachineFunction & MF) const1470b57cec5SDimitry 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 
197bdd1243dSDimitry Andric   Register AP =
198bdd1243dSDimitry Andric       MF.getInfo<HexagonMachineFunctionInfo>()->getStackAlignBaseReg();
199bdd1243dSDimitry Andric   if (AP.isValid())
200bdd1243dSDimitry Andric     Reserved.set(AP);
201bdd1243dSDimitry Andric 
2020b57cec5SDimitry Andric   for (int x = Reserved.find_first(); x >= 0; x = Reserved.find_next(x))
2030b57cec5SDimitry Andric     markSuperRegs(Reserved, x);
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   return Reserved;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOp,RegScavenger * RS) const208bdd1243dSDimitry Andric bool HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
2090b57cec5SDimitry Andric                                               int SPAdj, unsigned FIOp,
2100b57cec5SDimitry Andric                                               RegScavenger *RS) const {
211fe6060f1SDimitry Andric   static unsigned ReuseCount = 0;
2120b57cec5SDimitry Andric   //
2130b57cec5SDimitry Andric   // Hexagon_TODO: Do we need to enforce this for Hexagon?
2140b57cec5SDimitry Andric   assert(SPAdj == 0 && "Unexpected");
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   MachineInstr &MI = *II;
2170b57cec5SDimitry Andric   MachineBasicBlock &MB = *MI.getParent();
2180b57cec5SDimitry Andric   MachineFunction &MF = *MB.getParent();
2190b57cec5SDimitry Andric   auto &HST = MF.getSubtarget<HexagonSubtarget>();
2200b57cec5SDimitry Andric   auto &HII = *HST.getInstrInfo();
2210b57cec5SDimitry Andric   auto &HFI = *HST.getFrameLowering();
2220b57cec5SDimitry Andric 
2235ffd83dbSDimitry Andric   Register BP;
2240b57cec5SDimitry Andric   int FI = MI.getOperand(FIOp).getIndex();
2250b57cec5SDimitry Andric   // Select the base pointer (BP) and calculate the actual offset from BP
2260b57cec5SDimitry Andric   // to the beginning of the object at index FI.
227e8d8bef9SDimitry Andric   int Offset = HFI.getFrameIndexReference(MF, FI, BP).getFixed();
2280b57cec5SDimitry Andric   // Add the offset from the instruction.
2290b57cec5SDimitry Andric   int RealOffset = Offset + MI.getOperand(FIOp+1).getImm();
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
2320b57cec5SDimitry Andric   switch (Opc) {
2330b57cec5SDimitry Andric     case Hexagon::PS_fia:
2340b57cec5SDimitry Andric       MI.setDesc(HII.get(Hexagon::A2_addi));
2350b57cec5SDimitry Andric       MI.getOperand(FIOp).ChangeToImmediate(RealOffset);
23681ad6265SDimitry Andric       MI.removeOperand(FIOp+1);
237bdd1243dSDimitry Andric       return false;
2380b57cec5SDimitry Andric     case Hexagon::PS_fi:
2390b57cec5SDimitry Andric       // Set up the instruction for updating below.
2400b57cec5SDimitry Andric       MI.setDesc(HII.get(Hexagon::A2_addi));
2410b57cec5SDimitry Andric       break;
2420b57cec5SDimitry Andric   }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   if (!HII.isValidOffset(Opc, RealOffset, this)) {
2450b57cec5SDimitry Andric     // If the offset is not valid, calculate the address in a temporary
2460b57cec5SDimitry Andric     // register and use it with offset 0.
247fe6060f1SDimitry Andric     int InstOffset = 0;
248fe6060f1SDimitry Andric     // The actual base register (BP) is typically shared between many
249fe6060f1SDimitry Andric     // instructions where frame indices are being replaced. In scalar
250fe6060f1SDimitry Andric     // instructions the offset range is large, and the need for an extra
251fe6060f1SDimitry Andric     // add instruction is infrequent. Vector loads/stores, however, have
252fe6060f1SDimitry Andric     // a much smaller offset range: [-8, 7), or #s4. In those cases it
253fe6060f1SDimitry Andric     // makes sense to "standardize" the immediate in the "addi" instruction
254fe6060f1SDimitry Andric     // so that multiple loads/stores could be based on it.
255fe6060f1SDimitry Andric     bool IsPair = false;
256fe6060f1SDimitry Andric     switch (MI.getOpcode()) {
257fe6060f1SDimitry Andric       // All of these instructions have the same format: base+#s4.
258fe6060f1SDimitry Andric       case Hexagon::PS_vloadrw_ai:
259fe6060f1SDimitry Andric       case Hexagon::PS_vloadrw_nt_ai:
260fe6060f1SDimitry Andric       case Hexagon::PS_vstorerw_ai:
261fe6060f1SDimitry Andric       case Hexagon::PS_vstorerw_nt_ai:
262fe6060f1SDimitry Andric         IsPair = true;
263bdd1243dSDimitry Andric         [[fallthrough]];
264fe6060f1SDimitry Andric       case Hexagon::PS_vloadrv_ai:
265fe6060f1SDimitry Andric       case Hexagon::PS_vloadrv_nt_ai:
266fe6060f1SDimitry Andric       case Hexagon::PS_vstorerv_ai:
267fe6060f1SDimitry Andric       case Hexagon::PS_vstorerv_nt_ai:
268fe6060f1SDimitry Andric       case Hexagon::V6_vL32b_ai:
269fe6060f1SDimitry Andric       case Hexagon::V6_vS32b_ai: {
270fe6060f1SDimitry Andric         unsigned HwLen = HST.getVectorLength();
271fe6060f1SDimitry Andric         if (RealOffset % HwLen == 0) {
272fe6060f1SDimitry Andric           int VecOffset = RealOffset / HwLen;
273fe6060f1SDimitry Andric           // Rewrite the offset as "base + [-8, 7)".
274fe6060f1SDimitry Andric           VecOffset += 8;
275fe6060f1SDimitry Andric           // Pairs are expanded into two instructions: make sure that both
276fe6060f1SDimitry Andric           // can use the same base (i.e. VecOffset+1 is not a different
277fe6060f1SDimitry Andric           // multiple of 16 than VecOffset).
278fe6060f1SDimitry Andric           if (!IsPair || (VecOffset + 1) % 16 != 0) {
279fe6060f1SDimitry Andric             RealOffset = (VecOffset & -16) * HwLen;
280fe6060f1SDimitry Andric             InstOffset = (VecOffset % 16 - 8) * HwLen;
281fe6060f1SDimitry Andric           }
282fe6060f1SDimitry Andric         }
283fe6060f1SDimitry Andric       }
2840b57cec5SDimitry Andric     }
2850b57cec5SDimitry Andric 
286fe6060f1SDimitry Andric     // Search backwards in the block for "Reg = A2_addi BP, RealOffset".
287fe6060f1SDimitry Andric     // This will give us a chance to avoid creating a new register.
288fe6060f1SDimitry Andric     Register ReuseBP;
289fe6060f1SDimitry Andric 
290fe6060f1SDimitry Andric     if (ReuseCount < FrameIndexReuseLimit) {
291fe6060f1SDimitry Andric       unsigned SearchCount = 0, SearchRange = FrameIndexSearchRange;
292fe6060f1SDimitry Andric       SmallSet<Register,2> SeenVRegs;
293fe6060f1SDimitry Andric       bool PassedCall = false;
294fe6060f1SDimitry Andric       LiveRegUnits Defs(*this), Uses(*this);
295fe6060f1SDimitry Andric 
296fe6060f1SDimitry Andric       for (auto I = std::next(II.getReverse()), E = MB.rend(); I != E; ++I) {
297fe6060f1SDimitry Andric         if (SearchCount == SearchRange)
298fe6060f1SDimitry Andric           break;
299fe6060f1SDimitry Andric         ++SearchCount;
300fe6060f1SDimitry Andric         const MachineInstr &BI = *I;
301fe6060f1SDimitry Andric         LiveRegUnits::accumulateUsedDefed(BI, Defs, Uses, this);
302fe6060f1SDimitry Andric         PassedCall |= BI.isCall();
303fe6060f1SDimitry Andric         for (const MachineOperand &Op : BI.operands()) {
304fe6060f1SDimitry Andric           if (SeenVRegs.size() > 1)
305fe6060f1SDimitry Andric             break;
306fe6060f1SDimitry Andric           if (Op.isReg() && Op.getReg().isVirtual())
307fe6060f1SDimitry Andric             SeenVRegs.insert(Op.getReg());
308fe6060f1SDimitry Andric         }
309fe6060f1SDimitry Andric         if (BI.getOpcode() != Hexagon::A2_addi)
310fe6060f1SDimitry Andric           continue;
311fe6060f1SDimitry Andric         if (BI.getOperand(1).getReg() != BP)
312fe6060f1SDimitry Andric           continue;
313fe6060f1SDimitry Andric         const auto &Op2 = BI.getOperand(2);
314fe6060f1SDimitry Andric         if (!Op2.isImm() || Op2.getImm() != RealOffset)
315fe6060f1SDimitry Andric           continue;
316fe6060f1SDimitry Andric 
317fe6060f1SDimitry Andric         Register R = BI.getOperand(0).getReg();
318fe6060f1SDimitry Andric         if (R.isPhysical()) {
319fe6060f1SDimitry Andric           if (Defs.available(R))
320fe6060f1SDimitry Andric             ReuseBP = R;
321fe6060f1SDimitry Andric         } else if (R.isVirtual()) {
322fe6060f1SDimitry Andric           // Extending a range of a virtual register can be dangerous,
323fe6060f1SDimitry Andric           // since the scavenger will need to find a physical register
324fe6060f1SDimitry Andric           // for it. Avoid extending the range past a function call,
325fe6060f1SDimitry Andric           // and avoid overlapping it with another virtual register.
326fe6060f1SDimitry Andric           if (!PassedCall && SeenVRegs.size() <= 1)
327fe6060f1SDimitry Andric             ReuseBP = R;
328fe6060f1SDimitry Andric         }
329fe6060f1SDimitry Andric         break;
330fe6060f1SDimitry Andric       }
331fe6060f1SDimitry Andric       if (ReuseBP)
332fe6060f1SDimitry Andric         ++ReuseCount;
333fe6060f1SDimitry Andric     }
334fe6060f1SDimitry Andric 
335fe6060f1SDimitry Andric     auto &MRI = MF.getRegInfo();
336fe6060f1SDimitry Andric     if (!ReuseBP) {
337fe6060f1SDimitry Andric       ReuseBP = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
338fe6060f1SDimitry Andric       const DebugLoc &DL = MI.getDebugLoc();
339fe6060f1SDimitry Andric       BuildMI(MB, II, DL, HII.get(Hexagon::A2_addi), ReuseBP)
340fe6060f1SDimitry Andric         .addReg(BP)
341fe6060f1SDimitry Andric         .addImm(RealOffset);
342fe6060f1SDimitry Andric     }
343fe6060f1SDimitry Andric     BP = ReuseBP;
344fe6060f1SDimitry Andric     RealOffset = InstOffset;
345fe6060f1SDimitry Andric   }
346fe6060f1SDimitry Andric 
347fe6060f1SDimitry Andric   MI.getOperand(FIOp).ChangeToRegister(BP, false, false, false);
3480b57cec5SDimitry Andric   MI.getOperand(FIOp+1).ChangeToImmediate(RealOffset);
349bdd1243dSDimitry Andric   return false;
3500b57cec5SDimitry Andric }
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric 
shouldCoalesce(MachineInstr * MI,const TargetRegisterClass * SrcRC,unsigned SubReg,const TargetRegisterClass * DstRC,unsigned DstSubReg,const TargetRegisterClass * NewRC,LiveIntervals & LIS) const3530b57cec5SDimitry Andric bool HexagonRegisterInfo::shouldCoalesce(MachineInstr *MI,
3540b57cec5SDimitry Andric       const TargetRegisterClass *SrcRC, unsigned SubReg,
3550b57cec5SDimitry Andric       const TargetRegisterClass *DstRC, unsigned DstSubReg,
3560b57cec5SDimitry Andric       const TargetRegisterClass *NewRC, LiveIntervals &LIS) const {
3570b57cec5SDimitry Andric   // Coalescing will extend the live interval of the destination register.
3580b57cec5SDimitry Andric   // If the destination register is a vector pair, avoid introducing function
3590b57cec5SDimitry Andric   // calls into the interval, since it could result in a spilling of a pair
3600b57cec5SDimitry Andric   // instead of a single vector.
3610b57cec5SDimitry Andric   MachineFunction &MF = *MI->getParent()->getParent();
3620b57cec5SDimitry Andric   const HexagonSubtarget &HST = MF.getSubtarget<HexagonSubtarget>();
3630b57cec5SDimitry Andric   if (!HST.useHVXOps() || NewRC->getID() != Hexagon::HvxWRRegClass.getID())
3640b57cec5SDimitry Andric     return true;
3650b57cec5SDimitry Andric   bool SmallSrc = SrcRC->getID() == Hexagon::HvxVRRegClass.getID();
3660b57cec5SDimitry Andric   bool SmallDst = DstRC->getID() == Hexagon::HvxVRRegClass.getID();
3670b57cec5SDimitry Andric   if (!SmallSrc && !SmallDst)
3680b57cec5SDimitry Andric     return true;
3690b57cec5SDimitry Andric 
3708bcb0991SDimitry Andric   Register DstReg = MI->getOperand(0).getReg();
3718bcb0991SDimitry Andric   Register SrcReg = MI->getOperand(1).getReg();
3720b57cec5SDimitry Andric   const SlotIndexes &Indexes = *LIS.getSlotIndexes();
3730b57cec5SDimitry Andric   auto HasCall = [&Indexes] (const LiveInterval::Segment &S) {
3740b57cec5SDimitry Andric     for (SlotIndex I = S.start.getBaseIndex(), E = S.end.getBaseIndex();
3750b57cec5SDimitry Andric          I != E; I = I.getNextIndex()) {
3760b57cec5SDimitry Andric       if (const MachineInstr *MI = Indexes.getInstructionFromIndex(I))
3770b57cec5SDimitry Andric         if (MI->isCall())
3780b57cec5SDimitry Andric           return true;
3790b57cec5SDimitry Andric     }
3800b57cec5SDimitry Andric     return false;
3810b57cec5SDimitry Andric   };
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric   if (SmallSrc == SmallDst) {
3840b57cec5SDimitry Andric     // Both must be true, because the case for both being false was
3850b57cec5SDimitry Andric     // checked earlier. Both registers will be coalesced into a register
3860b57cec5SDimitry Andric     // of a wider class (HvxWR), and we don't want its live range to
3870b57cec5SDimitry Andric     // span over calls.
3880b57cec5SDimitry Andric     return !any_of(LIS.getInterval(DstReg), HasCall) &&
3890b57cec5SDimitry Andric            !any_of(LIS.getInterval(SrcReg), HasCall);
3900b57cec5SDimitry Andric   }
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   // If one register is large (HvxWR) and the other is small (HvxVR), then
3930b57cec5SDimitry Andric   // coalescing is ok if the large is already live across a function call,
3940b57cec5SDimitry Andric   // or if the small one is not.
395bdd1243dSDimitry Andric   Register SmallReg = SmallSrc ? SrcReg : DstReg;
396bdd1243dSDimitry Andric   Register LargeReg = SmallSrc ? DstReg : SrcReg;
3970b57cec5SDimitry Andric   return  any_of(LIS.getInterval(LargeReg), HasCall) ||
3980b57cec5SDimitry Andric          !any_of(LIS.getInterval(SmallReg), HasCall);
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric 
getFrameRegister(const MachineFunction & MF) const4020b57cec5SDimitry Andric Register HexagonRegisterInfo::getFrameRegister(const MachineFunction
4030b57cec5SDimitry Andric                                                &MF) const {
4040b57cec5SDimitry Andric   const HexagonFrameLowering *TFI = getFrameLowering(MF);
4050b57cec5SDimitry Andric   if (TFI->hasFP(MF))
4060b57cec5SDimitry Andric     return getFrameRegister();
4070b57cec5SDimitry Andric   return getStackRegister();
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric 
getFrameRegister() const411bdd1243dSDimitry Andric Register HexagonRegisterInfo::getFrameRegister() const {
4120b57cec5SDimitry Andric   return Hexagon::R30;
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric 
getStackRegister() const416bdd1243dSDimitry Andric Register HexagonRegisterInfo::getStackRegister() const {
4170b57cec5SDimitry Andric   return Hexagon::R29;
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric 
getHexagonSubRegIndex(const TargetRegisterClass & RC,unsigned GenIdx) const4210b57cec5SDimitry Andric unsigned HexagonRegisterInfo::getHexagonSubRegIndex(
4220b57cec5SDimitry Andric       const TargetRegisterClass &RC, unsigned GenIdx) const {
4230b57cec5SDimitry Andric   assert(GenIdx == Hexagon::ps_sub_lo || GenIdx == Hexagon::ps_sub_hi);
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   static const unsigned ISub[] = { Hexagon::isub_lo, Hexagon::isub_hi };
4260b57cec5SDimitry Andric   static const unsigned VSub[] = { Hexagon::vsub_lo, Hexagon::vsub_hi };
4270b57cec5SDimitry Andric   static const unsigned WSub[] = { Hexagon::wsub_lo, Hexagon::wsub_hi };
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   switch (RC.getID()) {
4300b57cec5SDimitry Andric     case Hexagon::CtrRegs64RegClassID:
4310b57cec5SDimitry Andric     case Hexagon::DoubleRegsRegClassID:
4320b57cec5SDimitry Andric       return ISub[GenIdx];
4330b57cec5SDimitry Andric     case Hexagon::HvxWRRegClassID:
4340b57cec5SDimitry Andric       return VSub[GenIdx];
4350b57cec5SDimitry Andric     case Hexagon::HvxVQRRegClassID:
4360b57cec5SDimitry Andric       return WSub[GenIdx];
4370b57cec5SDimitry Andric   }
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   if (const TargetRegisterClass *SuperRC = *RC.getSuperClasses())
4400b57cec5SDimitry Andric     return getHexagonSubRegIndex(*SuperRC, GenIdx);
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   llvm_unreachable("Invalid register class");
4430b57cec5SDimitry Andric }
4440b57cec5SDimitry Andric 
useFPForScavengingIndex(const MachineFunction & MF) const4450b57cec5SDimitry Andric bool HexagonRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF)
4460b57cec5SDimitry Andric       const {
4470b57cec5SDimitry Andric   return MF.getSubtarget<HexagonSubtarget>().getFrameLowering()->hasFP(MF);
4480b57cec5SDimitry Andric }
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric const TargetRegisterClass *
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const4510b57cec5SDimitry Andric HexagonRegisterInfo::getPointerRegClass(const MachineFunction &MF,
4520b57cec5SDimitry Andric                                         unsigned Kind) const {
4530b57cec5SDimitry Andric   return &Hexagon::IntRegsRegClass;
4540b57cec5SDimitry Andric }
455