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