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