1//===- NVPTXRegisterInfo.cpp - NVPTX Register Information -----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the NVPTX implementation of the TargetRegisterInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "NVPTXRegisterInfo.h"
14#include "MCTargetDesc/NVPTXBaseInfo.h"
15#include "MCTargetDesc/NVPTXInstPrinter.h"
16#include "NVPTX.h"
17#include "NVPTXSubtarget.h"
18#include "llvm/ADT/BitVector.h"
19#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineFunction.h"
21#include "llvm/CodeGen/TargetInstrInfo.h"
22#include "llvm/IR/Instructions.h"
23
24using namespace llvm;
25
26#define DEBUG_TYPE "nvptx-reg-info"
27
28NVPTXRegisterInfo::NVPTXRegisterInfo() : NVPTXGenRegisterInfo(0) {}
29
30#define GET_REGINFO_TARGET_DESC
31#include "NVPTXGenRegisterInfo.inc"
32
33/// NVPTX Callee Saved Registers
34const MCPhysReg *
35NVPTXRegisterInfo::getCalleeSavedRegs(const MachineFunction *) const {
36 static const MCPhysReg CalleeSavedRegs[] = { 0 };
37 return CalleeSavedRegs;
38}
39
40BitVector NVPTXRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
41 BitVector Reserved(getNumRegs());
42 for (unsigned Reg = NVPTX::ENVREG0; Reg <= NVPTX::ENVREG31; ++Reg) {
43 markSuperRegs(RegisterSet&: Reserved, Reg);
44 }
45 markSuperRegs(RegisterSet&: Reserved, Reg: NVPTX::VRFrame32);
46 markSuperRegs(RegisterSet&: Reserved, Reg: NVPTX::VRFrameLocal32);
47 markSuperRegs(RegisterSet&: Reserved, Reg: NVPTX::VRFrame64);
48 markSuperRegs(RegisterSet&: Reserved, Reg: NVPTX::VRFrameLocal64);
49 markSuperRegs(RegisterSet&: Reserved, Reg: NVPTX::VRDepot);
50 return Reserved;
51}
52
53bool NVPTXRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
54 int SPAdj, unsigned FIOperandNum,
55 RegScavenger *) const {
56 assert(SPAdj == 0 && "Unexpected");
57
58 MachineInstr &MI = *II;
59 if (MI.isLifetimeMarker()) {
60 MI.eraseFromParent();
61 return true;
62 }
63
64 const int FrameIndex = MI.getOperand(i: FIOperandNum).getIndex();
65
66 const MachineFunction &MF = *MI.getParent()->getParent();
67 const MachineFrameInfo &MFI = MF.getFrameInfo();
68 const int Offset = MFI.getObjectOffset(ObjectIdx: FrameIndex) +
69 MI.getOperand(i: FIOperandNum + 1).getImm();
70
71 // Local (addrspace 5) allocas are addressed through the local frame pointer
72 // (%SPL); everything else uses the generic frame pointer (%SP).
73 const AllocaInst *AI = MFI.getObjectAllocation(ObjectIdx: FrameIndex);
74 const Register FrameReg = AI && AI->getAddressSpace() == ADDRESS_SPACE_LOCAL
75 ? getFrameLocalRegister(MF)
76 : getFrameRegister(MF);
77 MI.getOperand(i: FIOperandNum).ChangeToRegister(Reg: FrameReg, isDef: false);
78 MI.getOperand(i: FIOperandNum + 1).ChangeToImmediate(ImmVal: Offset);
79 return false;
80}
81
82Register NVPTXRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
83 return MF.getDataLayout().getPointerSizeInBits(AS: ADDRESS_SPACE_GENERIC) == 64
84 ? NVPTX::VRFrame64
85 : NVPTX::VRFrame32;
86}
87
88Register
89NVPTXRegisterInfo::getFrameLocalRegister(const MachineFunction &MF) const {
90 return MF.getDataLayout().getPointerSizeInBits(AS: ADDRESS_SPACE_LOCAL) == 64
91 ? NVPTX::VRFrameLocal64
92 : NVPTX::VRFrameLocal32;
93}
94
95void NVPTXRegisterInfo::clearDebugRegisterMap() const {
96 DebugRegisterMap.clear();
97}
98
99static uint64_t encodeRegisterForDwarf(StringRef RegisterName) {
100 if (RegisterName.size() > 8)
101 // The name is more than 8 characters long, and so won't fit into 64 bits.
102 return 0;
103
104 // Encode the name string into a DWARF register number using cuda-gdb's
105 // encoding. See cuda_check_dwarf2_reg_ptx_virtual_register in cuda-tdep.c,
106 // https://github.com/NVIDIA/cuda-gdb/blob/e5cf3bddae520ffb326f95b4d98ce5c7474b828b/gdb/cuda/cuda-tdep.c#L353
107 // IE the bytes of the string are concatenated in reverse into a single
108 // number, which is stored in ULEB128, but in practice must be no more than 8
109 // bytes (excluding null terminator, which is not included).
110 uint64_t Result = 0;
111 for (unsigned char C : RegisterName)
112 Result = (Result << 8) | C;
113 return Result;
114}
115
116void NVPTXRegisterInfo::addToDebugRegisterMap(Register VirtReg,
117 StringRef RegisterName) const {
118 if (const uint64_t Encoded = encodeRegisterForDwarf(RegisterName))
119 DebugRegisterMap.insert(KV: {VirtReg, Encoded});
120}
121
122int64_t NVPTXRegisterInfo::getDwarfRegNum(MCRegister RegNum, bool isEH) const {
123 StringRef Name = NVPTXInstPrinter::getRegisterName(Reg: RegNum.id());
124 // In NVPTXFrameLowering.cpp, we do arrange for %Depot to be accessible from
125 // %SP. Using the %Depot register doesn't provide any debug info in
126 // cuda-gdb, but switching it to %SP does.
127 if (RegNum.id() == NVPTX::VRDepot)
128 Name = "%SP";
129 return encodeRegisterForDwarf(RegisterName: Name);
130}
131
132int64_t NVPTXRegisterInfo::getDwarfRegNumForVirtReg(Register RegNum,
133 bool isEH) const {
134 assert(RegNum.isVirtual());
135 if (const uint64_t Encoded = DebugRegisterMap.lookup(Val: RegNum))
136 return Encoded;
137 return -1;
138}
139