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 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 { 206fe6060f1SDimitry 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); 231*81ad6265SDimitry 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. 242fe6060f1SDimitry Andric int InstOffset = 0; 243fe6060f1SDimitry Andric // The actual base register (BP) is typically shared between many 244fe6060f1SDimitry Andric // instructions where frame indices are being replaced. In scalar 245fe6060f1SDimitry Andric // instructions the offset range is large, and the need for an extra 246fe6060f1SDimitry Andric // add instruction is infrequent. Vector loads/stores, however, have 247fe6060f1SDimitry Andric // a much smaller offset range: [-8, 7), or #s4. In those cases it 248fe6060f1SDimitry Andric // makes sense to "standardize" the immediate in the "addi" instruction 249fe6060f1SDimitry Andric // so that multiple loads/stores could be based on it. 250fe6060f1SDimitry Andric bool IsPair = false; 251fe6060f1SDimitry Andric switch (MI.getOpcode()) { 252fe6060f1SDimitry Andric // All of these instructions have the same format: base+#s4. 253fe6060f1SDimitry Andric case Hexagon::PS_vloadrw_ai: 254fe6060f1SDimitry Andric case Hexagon::PS_vloadrw_nt_ai: 255fe6060f1SDimitry Andric case Hexagon::PS_vstorerw_ai: 256fe6060f1SDimitry Andric case Hexagon::PS_vstorerw_nt_ai: 257fe6060f1SDimitry Andric IsPair = true; 258fe6060f1SDimitry Andric LLVM_FALLTHROUGH; 259fe6060f1SDimitry Andric case Hexagon::PS_vloadrv_ai: 260fe6060f1SDimitry Andric case Hexagon::PS_vloadrv_nt_ai: 261fe6060f1SDimitry Andric case Hexagon::PS_vstorerv_ai: 262fe6060f1SDimitry Andric case Hexagon::PS_vstorerv_nt_ai: 263fe6060f1SDimitry Andric case Hexagon::V6_vL32b_ai: 264fe6060f1SDimitry Andric case Hexagon::V6_vS32b_ai: { 265fe6060f1SDimitry Andric unsigned HwLen = HST.getVectorLength(); 266fe6060f1SDimitry Andric if (RealOffset % HwLen == 0) { 267fe6060f1SDimitry Andric int VecOffset = RealOffset / HwLen; 268fe6060f1SDimitry Andric // Rewrite the offset as "base + [-8, 7)". 269fe6060f1SDimitry Andric VecOffset += 8; 270fe6060f1SDimitry Andric // Pairs are expanded into two instructions: make sure that both 271fe6060f1SDimitry Andric // can use the same base (i.e. VecOffset+1 is not a different 272fe6060f1SDimitry Andric // multiple of 16 than VecOffset). 273fe6060f1SDimitry Andric if (!IsPair || (VecOffset + 1) % 16 != 0) { 274fe6060f1SDimitry Andric RealOffset = (VecOffset & -16) * HwLen; 275fe6060f1SDimitry Andric InstOffset = (VecOffset % 16 - 8) * HwLen; 276fe6060f1SDimitry Andric } 277fe6060f1SDimitry Andric } 278fe6060f1SDimitry Andric } 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 281fe6060f1SDimitry Andric // Search backwards in the block for "Reg = A2_addi BP, RealOffset". 282fe6060f1SDimitry Andric // This will give us a chance to avoid creating a new register. 283fe6060f1SDimitry Andric Register ReuseBP; 284fe6060f1SDimitry Andric 285fe6060f1SDimitry Andric if (ReuseCount < FrameIndexReuseLimit) { 286fe6060f1SDimitry Andric unsigned SearchCount = 0, SearchRange = FrameIndexSearchRange; 287fe6060f1SDimitry Andric SmallSet<Register,2> SeenVRegs; 288fe6060f1SDimitry Andric bool PassedCall = false; 289fe6060f1SDimitry Andric LiveRegUnits Defs(*this), Uses(*this); 290fe6060f1SDimitry Andric 291fe6060f1SDimitry Andric for (auto I = std::next(II.getReverse()), E = MB.rend(); I != E; ++I) { 292fe6060f1SDimitry Andric if (SearchCount == SearchRange) 293fe6060f1SDimitry Andric break; 294fe6060f1SDimitry Andric ++SearchCount; 295fe6060f1SDimitry Andric const MachineInstr &BI = *I; 296fe6060f1SDimitry Andric LiveRegUnits::accumulateUsedDefed(BI, Defs, Uses, this); 297fe6060f1SDimitry Andric PassedCall |= BI.isCall(); 298fe6060f1SDimitry Andric for (const MachineOperand &Op : BI.operands()) { 299fe6060f1SDimitry Andric if (SeenVRegs.size() > 1) 300fe6060f1SDimitry Andric break; 301fe6060f1SDimitry Andric if (Op.isReg() && Op.getReg().isVirtual()) 302fe6060f1SDimitry Andric SeenVRegs.insert(Op.getReg()); 303fe6060f1SDimitry Andric } 304fe6060f1SDimitry Andric if (BI.getOpcode() != Hexagon::A2_addi) 305fe6060f1SDimitry Andric continue; 306fe6060f1SDimitry Andric if (BI.getOperand(1).getReg() != BP) 307fe6060f1SDimitry Andric continue; 308fe6060f1SDimitry Andric const auto &Op2 = BI.getOperand(2); 309fe6060f1SDimitry Andric if (!Op2.isImm() || Op2.getImm() != RealOffset) 310fe6060f1SDimitry Andric continue; 311fe6060f1SDimitry Andric 312fe6060f1SDimitry Andric Register R = BI.getOperand(0).getReg(); 313fe6060f1SDimitry Andric if (R.isPhysical()) { 314fe6060f1SDimitry Andric if (Defs.available(R)) 315fe6060f1SDimitry Andric ReuseBP = R; 316fe6060f1SDimitry Andric } else if (R.isVirtual()) { 317fe6060f1SDimitry Andric // Extending a range of a virtual register can be dangerous, 318fe6060f1SDimitry Andric // since the scavenger will need to find a physical register 319fe6060f1SDimitry Andric // for it. Avoid extending the range past a function call, 320fe6060f1SDimitry Andric // and avoid overlapping it with another virtual register. 321fe6060f1SDimitry Andric if (!PassedCall && SeenVRegs.size() <= 1) 322fe6060f1SDimitry Andric ReuseBP = R; 323fe6060f1SDimitry Andric } 324fe6060f1SDimitry Andric break; 325fe6060f1SDimitry Andric } 326fe6060f1SDimitry Andric if (ReuseBP) 327fe6060f1SDimitry Andric ++ReuseCount; 328fe6060f1SDimitry Andric } 329fe6060f1SDimitry Andric 330fe6060f1SDimitry Andric auto &MRI = MF.getRegInfo(); 331fe6060f1SDimitry Andric if (!ReuseBP) { 332fe6060f1SDimitry Andric ReuseBP = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass); 333fe6060f1SDimitry Andric const DebugLoc &DL = MI.getDebugLoc(); 334fe6060f1SDimitry Andric BuildMI(MB, II, DL, HII.get(Hexagon::A2_addi), ReuseBP) 335fe6060f1SDimitry Andric .addReg(BP) 336fe6060f1SDimitry Andric .addImm(RealOffset); 337fe6060f1SDimitry Andric } 338fe6060f1SDimitry Andric BP = ReuseBP; 339fe6060f1SDimitry Andric RealOffset = InstOffset; 340fe6060f1SDimitry Andric } 341fe6060f1SDimitry Andric 342fe6060f1SDimitry 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