| 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 | |
| 24 | using namespace llvm; |
| 25 | |
| 26 | #define DEBUG_TYPE "nvptx-reg-info" |
| 27 | |
| 28 | NVPTXRegisterInfo::NVPTXRegisterInfo() : NVPTXGenRegisterInfo(0) {} |
| 29 | |
| 30 | #define GET_REGINFO_TARGET_DESC |
| 31 | #include "NVPTXGenRegisterInfo.inc" |
| 32 | |
| 33 | /// NVPTX Callee Saved Registers |
| 34 | const MCPhysReg * |
| 35 | NVPTXRegisterInfo::getCalleeSavedRegs(const MachineFunction *) const { |
| 36 | static const MCPhysReg CalleeSavedRegs[] = { 0 }; |
| 37 | return CalleeSavedRegs; |
| 38 | } |
| 39 | |
| 40 | BitVector 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 | |
| 53 | bool 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 | |
| 82 | Register NVPTXRegisterInfo::getFrameRegister(const MachineFunction &MF) const { |
| 83 | return MF.getDataLayout().getPointerSizeInBits(AS: ADDRESS_SPACE_GENERIC) == 64 |
| 84 | ? NVPTX::VRFrame64 |
| 85 | : NVPTX::VRFrame32; |
| 86 | } |
| 87 | |
| 88 | Register |
| 89 | NVPTXRegisterInfo::getFrameLocalRegister(const MachineFunction &MF) const { |
| 90 | return MF.getDataLayout().getPointerSizeInBits(AS: ADDRESS_SPACE_LOCAL) == 64 |
| 91 | ? NVPTX::VRFrameLocal64 |
| 92 | : NVPTX::VRFrameLocal32; |
| 93 | } |
| 94 | |
| 95 | void NVPTXRegisterInfo::clearDebugRegisterMap() const { |
| 96 | DebugRegisterMap.clear(); |
| 97 | } |
| 98 | |
| 99 | static 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 | |
| 116 | void NVPTXRegisterInfo::addToDebugRegisterMap(Register VirtReg, |
| 117 | StringRef RegisterName) const { |
| 118 | if (const uint64_t Encoded = encodeRegisterForDwarf(RegisterName)) |
| 119 | DebugRegisterMap.insert(KV: {VirtReg, Encoded}); |
| 120 | } |
| 121 | |
| 122 | int64_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 | |
| 132 | int64_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 | |