10b57cec5SDimitry Andric //===- NVPTXRegisterInfo.cpp - NVPTX 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 NVPTX implementation of the TargetRegisterInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "NVPTXRegisterInfo.h"
140b57cec5SDimitry Andric #include "NVPTX.h"
150b57cec5SDimitry Andric #include "NVPTXSubtarget.h"
16349cc55cSDimitry Andric #include "NVPTXTargetMachine.h"
170b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
220b57cec5SDimitry Andric #include "llvm/MC/MachineLocation.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #define DEBUG_TYPE "nvptx-reg-info"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric namespace llvm {
getNVPTXRegClassName(TargetRegisterClass const * RC)290b57cec5SDimitry Andric std::string getNVPTXRegClassName(TargetRegisterClass const *RC) {
300b57cec5SDimitry Andric   if (RC == &NVPTX::Float32RegsRegClass)
310b57cec5SDimitry Andric     return ".f32";
320b57cec5SDimitry Andric   if (RC == &NVPTX::Float64RegsRegClass)
330b57cec5SDimitry Andric     return ".f64";
340b57cec5SDimitry Andric   if (RC == &NVPTX::Int64RegsRegClass)
350b57cec5SDimitry Andric     // We use untyped (.b) integer registers here as NVCC does.
360b57cec5SDimitry Andric     // Correctness of generated code does not depend on register type,
370b57cec5SDimitry Andric     // but using .s/.u registers runs into ptxas bug that prevents
380b57cec5SDimitry Andric     // assembly of otherwise valid PTX into SASS. Despite PTX ISA
390b57cec5SDimitry Andric     // specifying only argument size for fp16 instructions, ptxas does
400b57cec5SDimitry Andric     // not allow using .s16 or .u16 arguments for .fp16
410b57cec5SDimitry Andric     // instructions. At the same time it allows using .s32/.u32
420b57cec5SDimitry Andric     // arguments for .fp16v2 instructions:
430b57cec5SDimitry Andric     //
440b57cec5SDimitry Andric     //   .reg .b16 rb16
450b57cec5SDimitry Andric     //   .reg .s16 rs16
460b57cec5SDimitry Andric     //   add.f16 rb16,rb16,rb16; // OK
470b57cec5SDimitry Andric     //   add.f16 rs16,rs16,rs16; // Arguments mismatch for instruction 'add'
480b57cec5SDimitry Andric     // but:
490b57cec5SDimitry Andric     //   .reg .b32 rb32
500b57cec5SDimitry Andric     //   .reg .s32 rs32
510b57cec5SDimitry Andric     //   add.f16v2 rb32,rb32,rb32; // OK
520b57cec5SDimitry Andric     //   add.f16v2 rs32,rs32,rs32; // OK
530b57cec5SDimitry Andric     return ".b64";
540b57cec5SDimitry Andric   if (RC == &NVPTX::Int32RegsRegClass)
550b57cec5SDimitry Andric     return ".b32";
560b57cec5SDimitry Andric   if (RC == &NVPTX::Int16RegsRegClass)
570b57cec5SDimitry Andric     return ".b16";
580b57cec5SDimitry Andric   if (RC == &NVPTX::Int1RegsRegClass)
590b57cec5SDimitry Andric     return ".pred";
600b57cec5SDimitry Andric   if (RC == &NVPTX::SpecialRegsRegClass)
610b57cec5SDimitry Andric     return "!Special!";
620b57cec5SDimitry Andric   return "INTERNAL";
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
getNVPTXRegClassStr(TargetRegisterClass const * RC)650b57cec5SDimitry Andric std::string getNVPTXRegClassStr(TargetRegisterClass const *RC) {
660b57cec5SDimitry Andric   if (RC == &NVPTX::Float32RegsRegClass)
670b57cec5SDimitry Andric     return "%f";
680b57cec5SDimitry Andric   if (RC == &NVPTX::Float64RegsRegClass)
690b57cec5SDimitry Andric     return "%fd";
700b57cec5SDimitry Andric   if (RC == &NVPTX::Int64RegsRegClass)
710b57cec5SDimitry Andric     return "%rd";
720b57cec5SDimitry Andric   if (RC == &NVPTX::Int32RegsRegClass)
730b57cec5SDimitry Andric     return "%r";
740b57cec5SDimitry Andric   if (RC == &NVPTX::Int16RegsRegClass)
750b57cec5SDimitry Andric     return "%rs";
760b57cec5SDimitry Andric   if (RC == &NVPTX::Int1RegsRegClass)
770b57cec5SDimitry Andric     return "%p";
780b57cec5SDimitry Andric   if (RC == &NVPTX::SpecialRegsRegClass)
790b57cec5SDimitry Andric     return "!Special!";
800b57cec5SDimitry Andric   return "INTERNAL";
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
NVPTXRegisterInfo()84bdd1243dSDimitry Andric NVPTXRegisterInfo::NVPTXRegisterInfo()
85bdd1243dSDimitry Andric     : NVPTXGenRegisterInfo(0), StrPool(StrAlloc) {}
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric #define GET_REGINFO_TARGET_DESC
880b57cec5SDimitry Andric #include "NVPTXGenRegisterInfo.inc"
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric /// NVPTX Callee Saved Registers
910b57cec5SDimitry Andric const MCPhysReg *
getCalleeSavedRegs(const MachineFunction *) const920b57cec5SDimitry Andric NVPTXRegisterInfo::getCalleeSavedRegs(const MachineFunction *) const {
930b57cec5SDimitry Andric   static const MCPhysReg CalleeSavedRegs[] = { 0 };
940b57cec5SDimitry Andric   return CalleeSavedRegs;
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric 
getReservedRegs(const MachineFunction & MF) const970b57cec5SDimitry Andric BitVector NVPTXRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
980b57cec5SDimitry Andric   BitVector Reserved(getNumRegs());
99349cc55cSDimitry Andric   for (unsigned Reg = NVPTX::ENVREG0; Reg <= NVPTX::ENVREG31; ++Reg) {
100349cc55cSDimitry Andric     markSuperRegs(Reserved, Reg);
101349cc55cSDimitry Andric   }
102349cc55cSDimitry Andric   markSuperRegs(Reserved, NVPTX::VRFrame32);
103349cc55cSDimitry Andric   markSuperRegs(Reserved, NVPTX::VRFrameLocal32);
104349cc55cSDimitry Andric   markSuperRegs(Reserved, NVPTX::VRFrame64);
105349cc55cSDimitry Andric   markSuperRegs(Reserved, NVPTX::VRFrameLocal64);
106349cc55cSDimitry Andric   markSuperRegs(Reserved, NVPTX::VRDepot);
1070b57cec5SDimitry Andric   return Reserved;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const110bdd1243dSDimitry Andric bool NVPTXRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
1110b57cec5SDimitry Andric                                             int SPAdj, unsigned FIOperandNum,
1120b57cec5SDimitry Andric                                             RegScavenger *RS) const {
1130b57cec5SDimitry Andric   assert(SPAdj == 0 && "Unexpected");
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   MachineInstr &MI = *II;
1160b57cec5SDimitry Andric   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   MachineFunction &MF = *MI.getParent()->getParent();
1190b57cec5SDimitry Andric   int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) +
1200b57cec5SDimitry Andric                MI.getOperand(FIOperandNum + 1).getImm();
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   // Using I0 as the frame pointer
123349cc55cSDimitry Andric   MI.getOperand(FIOperandNum).ChangeToRegister(getFrameRegister(MF), false);
1240b57cec5SDimitry Andric   MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
125bdd1243dSDimitry Andric   return false;
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric 
getFrameRegister(const MachineFunction & MF) const1280b57cec5SDimitry Andric Register NVPTXRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
129349cc55cSDimitry Andric   const NVPTXTargetMachine &TM =
130349cc55cSDimitry Andric       static_cast<const NVPTXTargetMachine &>(MF.getTarget());
131349cc55cSDimitry Andric   return TM.is64Bit() ? NVPTX::VRFrame64 : NVPTX::VRFrame32;
132349cc55cSDimitry Andric }
133349cc55cSDimitry Andric 
134349cc55cSDimitry Andric Register
getFrameLocalRegister(const MachineFunction & MF) const135349cc55cSDimitry Andric NVPTXRegisterInfo::getFrameLocalRegister(const MachineFunction &MF) const {
136349cc55cSDimitry Andric   const NVPTXTargetMachine &TM =
137349cc55cSDimitry Andric       static_cast<const NVPTXTargetMachine &>(MF.getTarget());
138349cc55cSDimitry Andric   return TM.is64Bit() ? NVPTX::VRFrameLocal64 : NVPTX::VRFrameLocal32;
1390b57cec5SDimitry Andric }
140