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