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