1 //===- AMDGPURegisterBankInfo.cpp -------------------------------*- C++ -*-==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// This file implements the targeting of the RegisterBankInfo class for
11 /// AMDGPU.
12 /// \todo This should be generated by TableGen.
13 //===----------------------------------------------------------------------===//
14 
15 #include "AMDGPURegisterBankInfo.h"
16 #include "AMDGPUInstrInfo.h"
17 #include "SIRegisterInfo.h"
18 #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
19 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
20 #include "llvm/CodeGen/TargetRegisterInfo.h"
21 #include "llvm/CodeGen/TargetSubtargetInfo.h"
22 #include "llvm/IR/Constants.h"
23 
24 #define GET_TARGET_REGBANK_IMPL
25 #include "AMDGPUGenRegisterBank.inc"
26 
27 // This file will be TableGen'ed at some point.
28 #include "AMDGPUGenRegisterBankInfo.def"
29 
30 using namespace llvm;
31 
32 AMDGPURegisterBankInfo::AMDGPURegisterBankInfo(const TargetRegisterInfo &TRI)
33     : AMDGPUGenRegisterBankInfo(),
34       TRI(static_cast<const SIRegisterInfo*>(&TRI)) {
35 
36   // HACK: Until this is fully tablegen'd
37   static bool AlreadyInit = false;
38   if (AlreadyInit)
39     return;
40 
41   AlreadyInit = true;
42 
43   const RegisterBank &RBSGPR = getRegBank(AMDGPU::SGPRRegBankID);
44   (void)RBSGPR;
45   assert(&RBSGPR == &AMDGPU::SGPRRegBank);
46 
47   const RegisterBank &RBVGPR = getRegBank(AMDGPU::VGPRRegBankID);
48   (void)RBVGPR;
49   assert(&RBVGPR == &AMDGPU::VGPRRegBank);
50 
51 }
52 
53 unsigned AMDGPURegisterBankInfo::copyCost(const RegisterBank &A,
54                                            const RegisterBank &B,
55                                            unsigned Size) const {
56   return RegisterBankInfo::copyCost(A, B, Size);
57 }
58 
59 const RegisterBank &AMDGPURegisterBankInfo::getRegBankFromRegClass(
60     const TargetRegisterClass &RC) const {
61 
62   if (TRI->isSGPRClass(&RC))
63     return getRegBank(AMDGPU::SGPRRegBankID);
64 
65   return getRegBank(AMDGPU::VGPRRegBankID);
66 }
67 
68 RegisterBankInfo::InstructionMappings
69 AMDGPURegisterBankInfo::getInstrAlternativeMappings(
70     const MachineInstr &MI) const {
71 
72   const MachineFunction &MF = *MI.getParent()->getParent();
73   const MachineRegisterInfo &MRI = MF.getRegInfo();
74 
75   unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
76 
77   InstructionMappings AltMappings;
78   switch (MI.getOpcode()) {
79   case TargetOpcode::G_LOAD: {
80     // FIXME: Should we be hard coding the size for these mappings?
81     const InstructionMapping &SSMapping = getInstructionMapping(
82         1, 1, getOperandsMapping(
83                   {AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size),
84                    AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 64)}),
85         2); // Num Operands
86     AltMappings.push_back(&SSMapping);
87 
88     const InstructionMapping &VVMapping = getInstructionMapping(
89         2, 1, getOperandsMapping(
90                   {AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size),
91                    AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 64)}),
92         2); // Num Operands
93     AltMappings.push_back(&VVMapping);
94 
95     // FIXME: Should this be the pointer-size (64-bits) or the size of the
96     // register that will hold the bufffer resourc (128-bits).
97     const InstructionMapping &VSMapping = getInstructionMapping(
98         3, 1, getOperandsMapping(
99                   {AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size),
100                    AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 64)}),
101         2); // Num Operands
102     AltMappings.push_back(&VSMapping);
103 
104     return AltMappings;
105 
106   }
107   default:
108     break;
109   }
110   return RegisterBankInfo::getInstrAlternativeMappings(MI);
111 }
112 
113 void AMDGPURegisterBankInfo::applyMappingImpl(
114     const OperandsMapper &OpdMapper) const {
115   return applyDefaultMapping(OpdMapper);
116 }
117 
118 static bool isInstrUniform(const MachineInstr &MI) {
119   if (!MI.hasOneMemOperand())
120     return false;
121 
122   const MachineMemOperand *MMO = *MI.memoperands_begin();
123   return AMDGPUInstrInfo::isUniformMMO(MMO);
124 }
125 
126 const RegisterBankInfo::InstructionMapping &
127 AMDGPURegisterBankInfo::getInstrMappingForLoad(const MachineInstr &MI) const {
128 
129   const MachineFunction &MF = *MI.getParent()->getParent();
130   const MachineRegisterInfo &MRI = MF.getRegInfo();
131   SmallVector<const ValueMapping*, 8> OpdsMapping(MI.getNumOperands());
132   unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
133   unsigned PtrSize = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
134 
135   const ValueMapping *ValMapping;
136   const ValueMapping *PtrMapping;
137 
138   if (isInstrUniform(MI)) {
139     // We have a uniform instruction so we want to use an SMRD load
140     ValMapping = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
141     PtrMapping = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, PtrSize);
142   } else {
143     ValMapping = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
144     // FIXME: What would happen if we used SGPRRegBankID here?
145     PtrMapping = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, PtrSize);
146   }
147 
148   OpdsMapping[0] = ValMapping;
149   OpdsMapping[1] = PtrMapping;
150   const RegisterBankInfo::InstructionMapping &Mapping = getInstructionMapping(
151       1, 1, getOperandsMapping(OpdsMapping), MI.getNumOperands());
152   return Mapping;
153 
154   // FIXME: Do we want to add a mapping for FLAT load, or should we just
155   // handle that during instruction selection?
156 }
157 
158 const RegisterBankInfo::InstructionMapping &
159 AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
160   const RegisterBankInfo::InstructionMapping &Mapping = getInstrMappingImpl(MI);
161 
162   if (Mapping.isValid())
163     return Mapping;
164 
165   const MachineFunction &MF = *MI.getParent()->getParent();
166   const MachineRegisterInfo &MRI = MF.getRegInfo();
167   SmallVector<const ValueMapping*, 8> OpdsMapping(MI.getNumOperands());
168 
169   bool IsComplete = true;
170   switch (MI.getOpcode()) {
171   default:
172     IsComplete = false;
173     break;
174   case AMDGPU::G_CONSTANT: {
175     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
176     OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
177     break;
178   }
179   case AMDGPU::G_GEP: {
180     for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
181       if (!MI.getOperand(i).isReg())
182         continue;
183 
184       unsigned Size = MRI.getType(MI.getOperand(i).getReg()).getSizeInBits();
185       OpdsMapping[i] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
186     }
187     break;
188   }
189   case AMDGPU::G_STORE: {
190     assert(MI.getOperand(0).isReg());
191     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
192     // FIXME: We need to specify a different reg bank once scalar stores
193     // are supported.
194     const ValueMapping *ValMapping =
195         AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
196     // FIXME: Depending on the type of store, the pointer could be in
197     // the SGPR Reg bank.
198     // FIXME: Pointer size should be based on the address space.
199     const ValueMapping *PtrMapping =
200         AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 64);
201 
202     OpdsMapping[0] = ValMapping;
203     OpdsMapping[1] = PtrMapping;
204     break;
205   }
206 
207   case AMDGPU::G_LOAD:
208     return getInstrMappingForLoad(MI);
209   }
210 
211   if (!IsComplete) {
212     unsigned BankID = AMDGPU::SGPRRegBankID;
213 
214     unsigned Size = 0;
215     for (unsigned Idx = 0; Idx < MI.getNumOperands(); ++Idx) {
216       // If the operand is not a register default to the size of the previous
217       // operand.
218       // FIXME: Can't we pull the types from the MachineInstr rather than the
219       // operands.
220       if (MI.getOperand(Idx).isReg())
221         Size = getSizeInBits(MI.getOperand(Idx).getReg(), MRI, *TRI);
222       OpdsMapping.push_back(AMDGPU::getValueMapping(BankID, Size));
223     }
224   }
225   return getInstructionMapping(1, 1, getOperandsMapping(OpdsMapping),
226                                MI.getNumOperands());
227 }
228