1 //===-- SIRegisterInfo.cpp - SI Register Information ---------------------===// 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 // 10 /// \file 11 /// \brief SI implementation of the TargetRegisterInfo class. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "SIRegisterInfo.h" 16 #include "AMDGPUSubtarget.h" 17 #include "SIInstrInfo.h" 18 #include "SIMachineFunctionInfo.h" 19 #include "llvm/CodeGen/MachineFrameInfo.h" 20 #include "llvm/CodeGen/MachineInstrBuilder.h" 21 #include "llvm/CodeGen/RegisterScavenging.h" 22 #include "llvm/IR/Function.h" 23 #include "llvm/IR/LLVMContext.h" 24 25 using namespace llvm; 26 27 static bool hasPressureSet(const int *PSets, unsigned PSetID) { 28 for (unsigned i = 0; PSets[i] != -1; ++i) { 29 if (PSets[i] == (int)PSetID) 30 return true; 31 } 32 return false; 33 } 34 35 void SIRegisterInfo::classifyPressureSet(unsigned PSetID, unsigned Reg, 36 BitVector &PressureSets) const { 37 for (MCRegUnitIterator U(Reg, this); U.isValid(); ++U) { 38 const int *PSets = getRegUnitPressureSets(*U); 39 if (hasPressureSet(PSets, PSetID)) { 40 PressureSets.set(PSetID); 41 break; 42 } 43 } 44 } 45 46 static cl::opt<bool> EnableSpillSGPRToSMEM( 47 "amdgpu-spill-sgpr-to-smem", 48 cl::desc("Use scalar stores to spill SGPRs if supported by subtarget"), 49 cl::init(false)); 50 51 static cl::opt<bool> EnableSpillSGPRToVGPR( 52 "amdgpu-spill-sgpr-to-vgpr", 53 cl::desc("Enable spilling VGPRs to SGPRs"), 54 cl::ReallyHidden, 55 cl::init(true)); 56 57 SIRegisterInfo::SIRegisterInfo(const SISubtarget &ST) : 58 AMDGPURegisterInfo(), 59 SGPRPressureSets(getNumRegPressureSets()), 60 VGPRPressureSets(getNumRegPressureSets()), 61 SpillSGPRToVGPR(false), 62 SpillSGPRToSMEM(false) { 63 if (EnableSpillSGPRToSMEM && ST.hasScalarStores()) 64 SpillSGPRToSMEM = true; 65 else if (EnableSpillSGPRToVGPR) 66 SpillSGPRToVGPR = true; 67 68 unsigned NumRegPressureSets = getNumRegPressureSets(); 69 70 SGPRSetID = NumRegPressureSets; 71 VGPRSetID = NumRegPressureSets; 72 73 for (unsigned i = 0; i < NumRegPressureSets; ++i) { 74 classifyPressureSet(i, AMDGPU::SGPR0, SGPRPressureSets); 75 classifyPressureSet(i, AMDGPU::VGPR0, VGPRPressureSets); 76 } 77 78 // Determine the number of reg units for each pressure set. 79 std::vector<unsigned> PressureSetRegUnits(NumRegPressureSets, 0); 80 for (unsigned i = 0, e = getNumRegUnits(); i != e; ++i) { 81 const int *PSets = getRegUnitPressureSets(i); 82 for (unsigned j = 0; PSets[j] != -1; ++j) { 83 ++PressureSetRegUnits[PSets[j]]; 84 } 85 } 86 87 unsigned VGPRMax = 0, SGPRMax = 0; 88 for (unsigned i = 0; i < NumRegPressureSets; ++i) { 89 if (isVGPRPressureSet(i) && PressureSetRegUnits[i] > VGPRMax) { 90 VGPRSetID = i; 91 VGPRMax = PressureSetRegUnits[i]; 92 continue; 93 } 94 if (isSGPRPressureSet(i) && PressureSetRegUnits[i] > SGPRMax) { 95 SGPRSetID = i; 96 SGPRMax = PressureSetRegUnits[i]; 97 } 98 } 99 100 assert(SGPRSetID < NumRegPressureSets && 101 VGPRSetID < NumRegPressureSets); 102 } 103 104 void SIRegisterInfo::reserveRegisterTuples(BitVector &Reserved, unsigned Reg) const { 105 MCRegAliasIterator R(Reg, this, true); 106 107 for (; R.isValid(); ++R) 108 Reserved.set(*R); 109 } 110 111 unsigned SIRegisterInfo::reservedPrivateSegmentBufferReg( 112 const MachineFunction &MF) const { 113 114 const SISubtarget &ST = MF.getSubtarget<SISubtarget>(); 115 unsigned BaseIdx = alignDown(ST.getMaxNumSGPRs(MF), 4) - 4; 116 unsigned BaseReg(AMDGPU::SGPR_32RegClass.getRegister(BaseIdx)); 117 return getMatchingSuperReg(BaseReg, AMDGPU::sub0, &AMDGPU::SReg_128RegClass); 118 } 119 120 static unsigned findPrivateSegmentWaveByteOffsetRegIndex(unsigned RegCount) { 121 unsigned Reg; 122 123 // Try to place it in a hole after PrivateSegmentBufferReg. 124 if (RegCount & 3) { 125 // We cannot put the segment buffer in (Idx - 4) ... (Idx - 1) due to 126 // alignment constraints, so we have a hole where can put the wave offset. 127 Reg = RegCount - 1; 128 } else { 129 // We can put the segment buffer in (Idx - 4) ... (Idx - 1) and put the 130 // wave offset before it. 131 Reg = RegCount - 5; 132 } 133 134 return Reg; 135 } 136 137 unsigned SIRegisterInfo::reservedPrivateSegmentWaveByteOffsetReg( 138 const MachineFunction &MF) const { 139 const SISubtarget &ST = MF.getSubtarget<SISubtarget>(); 140 unsigned Reg = findPrivateSegmentWaveByteOffsetRegIndex(ST.getMaxNumSGPRs(MF)); 141 return AMDGPU::SGPR_32RegClass.getRegister(Reg); 142 } 143 144 unsigned SIRegisterInfo::reservedStackPtrOffsetReg( 145 const MachineFunction &MF) const { 146 return AMDGPU::SGPR32; 147 } 148 149 BitVector SIRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 150 BitVector Reserved(getNumRegs()); 151 152 // EXEC_LO and EXEC_HI could be allocated and used as regular register, but 153 // this seems likely to result in bugs, so I'm marking them as reserved. 154 reserveRegisterTuples(Reserved, AMDGPU::EXEC); 155 reserveRegisterTuples(Reserved, AMDGPU::FLAT_SCR); 156 157 // M0 has to be reserved so that llvm accepts it as a live-in into a block. 158 reserveRegisterTuples(Reserved, AMDGPU::M0); 159 160 // Reserve the memory aperture registers. 161 reserveRegisterTuples(Reserved, AMDGPU::SRC_SHARED_BASE); 162 reserveRegisterTuples(Reserved, AMDGPU::SRC_SHARED_LIMIT); 163 reserveRegisterTuples(Reserved, AMDGPU::SRC_PRIVATE_BASE); 164 reserveRegisterTuples(Reserved, AMDGPU::SRC_PRIVATE_LIMIT); 165 166 // Reserve Trap Handler registers - support is not implemented in Codegen. 167 reserveRegisterTuples(Reserved, AMDGPU::TBA); 168 reserveRegisterTuples(Reserved, AMDGPU::TMA); 169 reserveRegisterTuples(Reserved, AMDGPU::TTMP0_TTMP1); 170 reserveRegisterTuples(Reserved, AMDGPU::TTMP2_TTMP3); 171 reserveRegisterTuples(Reserved, AMDGPU::TTMP4_TTMP5); 172 reserveRegisterTuples(Reserved, AMDGPU::TTMP6_TTMP7); 173 reserveRegisterTuples(Reserved, AMDGPU::TTMP8_TTMP9); 174 reserveRegisterTuples(Reserved, AMDGPU::TTMP10_TTMP11); 175 reserveRegisterTuples(Reserved, AMDGPU::TTMP12_TTMP13); 176 reserveRegisterTuples(Reserved, AMDGPU::TTMP14_TTMP15); 177 178 const SISubtarget &ST = MF.getSubtarget<SISubtarget>(); 179 180 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF); 181 unsigned TotalNumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs(); 182 for (unsigned i = MaxNumSGPRs; i < TotalNumSGPRs; ++i) { 183 unsigned Reg = AMDGPU::SGPR_32RegClass.getRegister(i); 184 reserveRegisterTuples(Reserved, Reg); 185 } 186 187 unsigned MaxNumVGPRs = ST.getMaxNumVGPRs(MF); 188 unsigned TotalNumVGPRs = AMDGPU::VGPR_32RegClass.getNumRegs(); 189 for (unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i) { 190 unsigned Reg = AMDGPU::VGPR_32RegClass.getRegister(i); 191 reserveRegisterTuples(Reserved, Reg); 192 } 193 194 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>(); 195 196 unsigned ScratchWaveOffsetReg = MFI->getScratchWaveOffsetReg(); 197 if (ScratchWaveOffsetReg != AMDGPU::NoRegister) { 198 // Reserve 1 SGPR for scratch wave offset in case we need to spill. 199 reserveRegisterTuples(Reserved, ScratchWaveOffsetReg); 200 } 201 202 unsigned ScratchRSrcReg = MFI->getScratchRSrcReg(); 203 if (ScratchRSrcReg != AMDGPU::NoRegister) { 204 // Reserve 4 SGPRs for the scratch buffer resource descriptor in case we need 205 // to spill. 206 // TODO: May need to reserve a VGPR if doing LDS spilling. 207 reserveRegisterTuples(Reserved, ScratchRSrcReg); 208 assert(!isSubRegister(ScratchRSrcReg, ScratchWaveOffsetReg)); 209 } 210 211 // We have to assume the SP is needed in case there are calls in the function, 212 // which is detected after the function is lowered. If we aren't really going 213 // to need SP, don't bother reserving it. 214 unsigned StackPtrReg = MFI->getStackPtrOffsetReg(); 215 216 if (StackPtrReg != AMDGPU::NoRegister) { 217 reserveRegisterTuples(Reserved, StackPtrReg); 218 assert(!isSubRegister(ScratchRSrcReg, StackPtrReg)); 219 } 220 221 unsigned FrameReg = MFI->getFrameOffsetReg(); 222 if (FrameReg != AMDGPU::NoRegister) { 223 reserveRegisterTuples(Reserved, FrameReg); 224 assert(!isSubRegister(ScratchRSrcReg, FrameReg)); 225 } 226 227 return Reserved; 228 } 229 230 bool SIRegisterInfo::requiresRegisterScavenging(const MachineFunction &Fn) const { 231 const SIMachineFunctionInfo *Info = Fn.getInfo<SIMachineFunctionInfo>(); 232 if (Info->isEntryFunction()) { 233 const MachineFrameInfo &MFI = Fn.getFrameInfo(); 234 return MFI.hasStackObjects() || MFI.hasCalls(); 235 } 236 237 // May need scavenger for dealing with callee saved registers. 238 return true; 239 } 240 241 bool SIRegisterInfo::requiresFrameIndexScavenging( 242 const MachineFunction &MF) const { 243 const MachineFrameInfo &MFI = MF.getFrameInfo(); 244 if (MFI.hasStackObjects()) 245 return true; 246 247 // May need to deal with callee saved registers. 248 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>(); 249 return !Info->isEntryFunction(); 250 } 251 252 bool SIRegisterInfo::requiresFrameIndexReplacementScavenging( 253 const MachineFunction &MF) const { 254 // m0 is needed for the scalar store offset. m0 is unallocatable, so we can't 255 // create a virtual register for it during frame index elimination, so the 256 // scavenger is directly needed. 257 return MF.getFrameInfo().hasStackObjects() && 258 MF.getSubtarget<SISubtarget>().hasScalarStores() && 259 MF.getInfo<SIMachineFunctionInfo>()->hasSpilledSGPRs(); 260 } 261 262 bool SIRegisterInfo::requiresVirtualBaseRegisters( 263 const MachineFunction &) const { 264 // There are no special dedicated stack or frame pointers. 265 return true; 266 } 267 268 bool SIRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const { 269 // This helps catch bugs as verifier errors. 270 return true; 271 } 272 273 int64_t SIRegisterInfo::getMUBUFInstrOffset(const MachineInstr *MI) const { 274 assert(SIInstrInfo::isMUBUF(*MI)); 275 276 int OffIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(), 277 AMDGPU::OpName::offset); 278 return MI->getOperand(OffIdx).getImm(); 279 } 280 281 int64_t SIRegisterInfo::getFrameIndexInstrOffset(const MachineInstr *MI, 282 int Idx) const { 283 if (!SIInstrInfo::isMUBUF(*MI)) 284 return 0; 285 286 assert(Idx == AMDGPU::getNamedOperandIdx(MI->getOpcode(), 287 AMDGPU::OpName::vaddr) && 288 "Should never see frame index on non-address operand"); 289 290 return getMUBUFInstrOffset(MI); 291 } 292 293 bool SIRegisterInfo::needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const { 294 if (!MI->mayLoadOrStore()) 295 return false; 296 297 int64_t FullOffset = Offset + getMUBUFInstrOffset(MI); 298 299 return !isUInt<12>(FullOffset); 300 } 301 302 void SIRegisterInfo::materializeFrameBaseRegister(MachineBasicBlock *MBB, 303 unsigned BaseReg, 304 int FrameIdx, 305 int64_t Offset) const { 306 MachineBasicBlock::iterator Ins = MBB->begin(); 307 DebugLoc DL; // Defaults to "unknown" 308 309 if (Ins != MBB->end()) 310 DL = Ins->getDebugLoc(); 311 312 MachineFunction *MF = MBB->getParent(); 313 const SISubtarget &Subtarget = MF->getSubtarget<SISubtarget>(); 314 const SIInstrInfo *TII = Subtarget.getInstrInfo(); 315 316 if (Offset == 0) { 317 BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::V_MOV_B32_e32), BaseReg) 318 .addFrameIndex(FrameIdx); 319 return; 320 } 321 322 MachineRegisterInfo &MRI = MF->getRegInfo(); 323 unsigned OffsetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 324 325 unsigned FIReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 326 327 BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::S_MOV_B32), OffsetReg) 328 .addImm(Offset); 329 BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::V_MOV_B32_e32), FIReg) 330 .addFrameIndex(FrameIdx); 331 332 TII->getAddNoCarry(*MBB, Ins, DL, BaseReg) 333 .addReg(OffsetReg, RegState::Kill) 334 .addReg(FIReg); 335 } 336 337 void SIRegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg, 338 int64_t Offset) const { 339 340 MachineBasicBlock *MBB = MI.getParent(); 341 MachineFunction *MF = MBB->getParent(); 342 const SISubtarget &Subtarget = MF->getSubtarget<SISubtarget>(); 343 const SIInstrInfo *TII = Subtarget.getInstrInfo(); 344 345 #ifndef NDEBUG 346 // FIXME: Is it possible to be storing a frame index to itself? 347 bool SeenFI = false; 348 for (const MachineOperand &MO: MI.operands()) { 349 if (MO.isFI()) { 350 if (SeenFI) 351 llvm_unreachable("should not see multiple frame indices"); 352 353 SeenFI = true; 354 } 355 } 356 #endif 357 358 MachineOperand *FIOp = TII->getNamedOperand(MI, AMDGPU::OpName::vaddr); 359 assert(FIOp && FIOp->isFI() && "frame index must be address operand"); 360 assert(TII->isMUBUF(MI)); 361 assert(TII->getNamedOperand(MI, AMDGPU::OpName::soffset)->getReg() == 362 MF->getInfo<SIMachineFunctionInfo>()->getFrameOffsetReg() && 363 "should only be seeing frame offset relative FrameIndex"); 364 365 366 MachineOperand *OffsetOp = TII->getNamedOperand(MI, AMDGPU::OpName::offset); 367 int64_t NewOffset = OffsetOp->getImm() + Offset; 368 assert(isUInt<12>(NewOffset) && "offset should be legal"); 369 370 FIOp->ChangeToRegister(BaseReg, false); 371 OffsetOp->setImm(NewOffset); 372 } 373 374 bool SIRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI, 375 unsigned BaseReg, 376 int64_t Offset) const { 377 if (!SIInstrInfo::isMUBUF(*MI)) 378 return false; 379 380 int64_t NewOffset = Offset + getMUBUFInstrOffset(MI); 381 382 return isUInt<12>(NewOffset); 383 } 384 385 const TargetRegisterClass *SIRegisterInfo::getPointerRegClass( 386 const MachineFunction &MF, unsigned Kind) const { 387 // This is inaccurate. It depends on the instruction and address space. The 388 // only place where we should hit this is for dealing with frame indexes / 389 // private accesses, so this is correct in that case. 390 return &AMDGPU::VGPR_32RegClass; 391 } 392 393 static unsigned getNumSubRegsForSpillOp(unsigned Op) { 394 395 switch (Op) { 396 case AMDGPU::SI_SPILL_S512_SAVE: 397 case AMDGPU::SI_SPILL_S512_RESTORE: 398 case AMDGPU::SI_SPILL_V512_SAVE: 399 case AMDGPU::SI_SPILL_V512_RESTORE: 400 return 16; 401 case AMDGPU::SI_SPILL_S256_SAVE: 402 case AMDGPU::SI_SPILL_S256_RESTORE: 403 case AMDGPU::SI_SPILL_V256_SAVE: 404 case AMDGPU::SI_SPILL_V256_RESTORE: 405 return 8; 406 case AMDGPU::SI_SPILL_S128_SAVE: 407 case AMDGPU::SI_SPILL_S128_RESTORE: 408 case AMDGPU::SI_SPILL_V128_SAVE: 409 case AMDGPU::SI_SPILL_V128_RESTORE: 410 return 4; 411 case AMDGPU::SI_SPILL_V96_SAVE: 412 case AMDGPU::SI_SPILL_V96_RESTORE: 413 return 3; 414 case AMDGPU::SI_SPILL_S64_SAVE: 415 case AMDGPU::SI_SPILL_S64_RESTORE: 416 case AMDGPU::SI_SPILL_V64_SAVE: 417 case AMDGPU::SI_SPILL_V64_RESTORE: 418 return 2; 419 case AMDGPU::SI_SPILL_S32_SAVE: 420 case AMDGPU::SI_SPILL_S32_RESTORE: 421 case AMDGPU::SI_SPILL_V32_SAVE: 422 case AMDGPU::SI_SPILL_V32_RESTORE: 423 return 1; 424 default: llvm_unreachable("Invalid spill opcode"); 425 } 426 } 427 428 static int getOffsetMUBUFStore(unsigned Opc) { 429 switch (Opc) { 430 case AMDGPU::BUFFER_STORE_DWORD_OFFEN: 431 return AMDGPU::BUFFER_STORE_DWORD_OFFSET; 432 case AMDGPU::BUFFER_STORE_BYTE_OFFEN: 433 return AMDGPU::BUFFER_STORE_BYTE_OFFSET; 434 case AMDGPU::BUFFER_STORE_SHORT_OFFEN: 435 return AMDGPU::BUFFER_STORE_SHORT_OFFSET; 436 case AMDGPU::BUFFER_STORE_DWORDX2_OFFEN: 437 return AMDGPU::BUFFER_STORE_DWORDX2_OFFSET; 438 case AMDGPU::BUFFER_STORE_DWORDX4_OFFEN: 439 return AMDGPU::BUFFER_STORE_DWORDX4_OFFSET; 440 case AMDGPU::BUFFER_STORE_SHORT_D16_HI_OFFEN: 441 return AMDGPU::BUFFER_STORE_SHORT_D16_HI_OFFSET; 442 case AMDGPU::BUFFER_STORE_BYTE_D16_HI_OFFEN: 443 return AMDGPU::BUFFER_STORE_BYTE_D16_HI_OFFSET; 444 default: 445 return -1; 446 } 447 } 448 449 static int getOffsetMUBUFLoad(unsigned Opc) { 450 switch (Opc) { 451 case AMDGPU::BUFFER_LOAD_DWORD_OFFEN: 452 return AMDGPU::BUFFER_LOAD_DWORD_OFFSET; 453 case AMDGPU::BUFFER_LOAD_UBYTE_OFFEN: 454 return AMDGPU::BUFFER_LOAD_UBYTE_OFFSET; 455 case AMDGPU::BUFFER_LOAD_SBYTE_OFFEN: 456 return AMDGPU::BUFFER_LOAD_SBYTE_OFFSET; 457 case AMDGPU::BUFFER_LOAD_USHORT_OFFEN: 458 return AMDGPU::BUFFER_LOAD_USHORT_OFFSET; 459 case AMDGPU::BUFFER_LOAD_SSHORT_OFFEN: 460 return AMDGPU::BUFFER_LOAD_SSHORT_OFFSET; 461 case AMDGPU::BUFFER_LOAD_DWORDX2_OFFEN: 462 return AMDGPU::BUFFER_LOAD_DWORDX2_OFFSET; 463 case AMDGPU::BUFFER_LOAD_DWORDX4_OFFEN: 464 return AMDGPU::BUFFER_LOAD_DWORDX4_OFFSET; 465 case AMDGPU::BUFFER_LOAD_UBYTE_D16_OFFEN: 466 return AMDGPU::BUFFER_LOAD_UBYTE_D16_OFFSET; 467 case AMDGPU::BUFFER_LOAD_UBYTE_D16_HI_OFFEN: 468 return AMDGPU::BUFFER_LOAD_UBYTE_D16_HI_OFFSET; 469 case AMDGPU::BUFFER_LOAD_SBYTE_D16_OFFEN: 470 return AMDGPU::BUFFER_LOAD_SBYTE_D16_OFFSET; 471 case AMDGPU::BUFFER_LOAD_SBYTE_D16_HI_OFFEN: 472 return AMDGPU::BUFFER_LOAD_SBYTE_D16_HI_OFFSET; 473 case AMDGPU::BUFFER_LOAD_SHORT_D16_OFFEN: 474 return AMDGPU::BUFFER_LOAD_SHORT_D16_OFFSET; 475 case AMDGPU::BUFFER_LOAD_SHORT_D16_HI_OFFEN: 476 return AMDGPU::BUFFER_LOAD_SHORT_D16_HI_OFFSET; 477 default: 478 return -1; 479 } 480 } 481 482 // This differs from buildSpillLoadStore by only scavenging a VGPR. It does not 483 // need to handle the case where an SGPR may need to be spilled while spilling. 484 static bool buildMUBUFOffsetLoadStore(const SIInstrInfo *TII, 485 MachineFrameInfo &MFI, 486 MachineBasicBlock::iterator MI, 487 int Index, 488 int64_t Offset) { 489 MachineBasicBlock *MBB = MI->getParent(); 490 const DebugLoc &DL = MI->getDebugLoc(); 491 bool IsStore = MI->mayStore(); 492 493 unsigned Opc = MI->getOpcode(); 494 int LoadStoreOp = IsStore ? 495 getOffsetMUBUFStore(Opc) : getOffsetMUBUFLoad(Opc); 496 if (LoadStoreOp == -1) 497 return false; 498 499 const MachineOperand *Reg = TII->getNamedOperand(*MI, AMDGPU::OpName::vdata); 500 MachineInstrBuilder NewMI = BuildMI(*MBB, MI, DL, TII->get(LoadStoreOp)) 501 .add(*Reg) 502 .add(*TII->getNamedOperand(*MI, AMDGPU::OpName::srsrc)) 503 .add(*TII->getNamedOperand(*MI, AMDGPU::OpName::soffset)) 504 .addImm(Offset) 505 .addImm(0) // glc 506 .addImm(0) // slc 507 .addImm(0) // tfe 508 .setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); 509 510 const MachineOperand *VDataIn = TII->getNamedOperand(*MI, 511 AMDGPU::OpName::vdata_in); 512 if (VDataIn) 513 NewMI.add(*VDataIn); 514 return true; 515 } 516 517 void SIRegisterInfo::buildSpillLoadStore(MachineBasicBlock::iterator MI, 518 unsigned LoadStoreOp, 519 int Index, 520 unsigned ValueReg, 521 bool IsKill, 522 unsigned ScratchRsrcReg, 523 unsigned ScratchOffsetReg, 524 int64_t InstOffset, 525 MachineMemOperand *MMO, 526 RegScavenger *RS) const { 527 MachineBasicBlock *MBB = MI->getParent(); 528 MachineFunction *MF = MI->getParent()->getParent(); 529 const SISubtarget &ST = MF->getSubtarget<SISubtarget>(); 530 const SIInstrInfo *TII = ST.getInstrInfo(); 531 const MachineFrameInfo &MFI = MF->getFrameInfo(); 532 533 const MCInstrDesc &Desc = TII->get(LoadStoreOp); 534 const DebugLoc &DL = MI->getDebugLoc(); 535 bool IsStore = Desc.mayStore(); 536 537 bool RanOutOfSGPRs = false; 538 bool Scavenged = false; 539 unsigned SOffset = ScratchOffsetReg; 540 541 const TargetRegisterClass *RC = getRegClassForReg(MF->getRegInfo(), ValueReg); 542 unsigned NumSubRegs = AMDGPU::getRegBitWidth(RC->getID()) / 32; 543 unsigned Size = NumSubRegs * 4; 544 int64_t Offset = InstOffset + MFI.getObjectOffset(Index); 545 const int64_t OriginalImmOffset = Offset; 546 547 unsigned Align = MFI.getObjectAlignment(Index); 548 const MachinePointerInfo &BasePtrInfo = MMO->getPointerInfo(); 549 550 if (!isUInt<12>(Offset + Size)) { 551 SOffset = AMDGPU::NoRegister; 552 553 // We don't have access to the register scavenger if this function is called 554 // during PEI::scavengeFrameVirtualRegs(). 555 if (RS) 556 SOffset = RS->FindUnusedReg(&AMDGPU::SGPR_32RegClass); 557 558 if (SOffset == AMDGPU::NoRegister) { 559 // There are no free SGPRs, and since we are in the process of spilling 560 // VGPRs too. Since we need a VGPR in order to spill SGPRs (this is true 561 // on SI/CI and on VI it is true until we implement spilling using scalar 562 // stores), we have no way to free up an SGPR. Our solution here is to 563 // add the offset directly to the ScratchOffset register, and then 564 // subtract the offset after the spill to return ScratchOffset to it's 565 // original value. 566 RanOutOfSGPRs = true; 567 SOffset = ScratchOffsetReg; 568 } else { 569 Scavenged = true; 570 } 571 572 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_ADD_U32), SOffset) 573 .addReg(ScratchOffsetReg) 574 .addImm(Offset); 575 576 Offset = 0; 577 } 578 579 const unsigned EltSize = 4; 580 581 for (unsigned i = 0, e = NumSubRegs; i != e; ++i, Offset += EltSize) { 582 unsigned SubReg = NumSubRegs == 1 ? 583 ValueReg : getSubReg(ValueReg, getSubRegFromChannel(i)); 584 585 unsigned SOffsetRegState = 0; 586 unsigned SrcDstRegState = getDefRegState(!IsStore); 587 if (i + 1 == e) { 588 SOffsetRegState |= getKillRegState(Scavenged); 589 // The last implicit use carries the "Kill" flag. 590 SrcDstRegState |= getKillRegState(IsKill); 591 } 592 593 MachinePointerInfo PInfo = BasePtrInfo.getWithOffset(EltSize * i); 594 MachineMemOperand *NewMMO 595 = MF->getMachineMemOperand(PInfo, MMO->getFlags(), 596 EltSize, MinAlign(Align, EltSize * i)); 597 598 auto MIB = BuildMI(*MBB, MI, DL, Desc) 599 .addReg(SubReg, getDefRegState(!IsStore) | getKillRegState(IsKill)) 600 .addReg(ScratchRsrcReg) 601 .addReg(SOffset, SOffsetRegState) 602 .addImm(Offset) 603 .addImm(0) // glc 604 .addImm(0) // slc 605 .addImm(0) // tfe 606 .addMemOperand(NewMMO); 607 608 if (NumSubRegs > 1) 609 MIB.addReg(ValueReg, RegState::Implicit | SrcDstRegState); 610 } 611 612 if (RanOutOfSGPRs) { 613 // Subtract the offset we added to the ScratchOffset register. 614 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_SUB_U32), ScratchOffsetReg) 615 .addReg(ScratchOffsetReg) 616 .addImm(OriginalImmOffset); 617 } 618 } 619 620 static std::pair<unsigned, unsigned> getSpillEltSize(unsigned SuperRegSize, 621 bool Store) { 622 if (SuperRegSize % 16 == 0) { 623 return { 16, Store ? AMDGPU::S_BUFFER_STORE_DWORDX4_SGPR : 624 AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR }; 625 } 626 627 if (SuperRegSize % 8 == 0) { 628 return { 8, Store ? AMDGPU::S_BUFFER_STORE_DWORDX2_SGPR : 629 AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR }; 630 } 631 632 return { 4, Store ? AMDGPU::S_BUFFER_STORE_DWORD_SGPR : 633 AMDGPU::S_BUFFER_LOAD_DWORD_SGPR}; 634 } 635 636 bool SIRegisterInfo::spillSGPR(MachineBasicBlock::iterator MI, 637 int Index, 638 RegScavenger *RS, 639 bool OnlyToVGPR) const { 640 MachineBasicBlock *MBB = MI->getParent(); 641 MachineFunction *MF = MBB->getParent(); 642 SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>(); 643 644 ArrayRef<SIMachineFunctionInfo::SpilledReg> VGPRSpills 645 = MFI->getSGPRToVGPRSpills(Index); 646 bool SpillToVGPR = !VGPRSpills.empty(); 647 if (OnlyToVGPR && !SpillToVGPR) 648 return false; 649 650 MachineRegisterInfo &MRI = MF->getRegInfo(); 651 const SISubtarget &ST = MF->getSubtarget<SISubtarget>(); 652 const SIInstrInfo *TII = ST.getInstrInfo(); 653 654 unsigned SuperReg = MI->getOperand(0).getReg(); 655 bool IsKill = MI->getOperand(0).isKill(); 656 const DebugLoc &DL = MI->getDebugLoc(); 657 658 MachineFrameInfo &FrameInfo = MF->getFrameInfo(); 659 660 bool SpillToSMEM = spillSGPRToSMEM(); 661 if (SpillToSMEM && OnlyToVGPR) 662 return false; 663 664 assert(SuperReg != AMDGPU::M0 && "m0 should never spill"); 665 666 unsigned OffsetReg = AMDGPU::M0; 667 unsigned M0CopyReg = AMDGPU::NoRegister; 668 669 if (SpillToSMEM) { 670 if (RS->isRegUsed(AMDGPU::M0)) { 671 M0CopyReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 672 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::COPY), M0CopyReg) 673 .addReg(AMDGPU::M0); 674 } 675 } 676 677 unsigned ScalarStoreOp; 678 unsigned EltSize = 4; 679 const TargetRegisterClass *RC = getPhysRegClass(SuperReg); 680 if (SpillToSMEM && isSGPRClass(RC)) { 681 // XXX - if private_element_size is larger than 4 it might be useful to be 682 // able to spill wider vmem spills. 683 std::tie(EltSize, ScalarStoreOp) = 684 getSpillEltSize(getRegSizeInBits(*RC) / 8, true); 685 } 686 687 ArrayRef<int16_t> SplitParts = getRegSplitParts(RC, EltSize); 688 unsigned NumSubRegs = SplitParts.empty() ? 1 : SplitParts.size(); 689 690 // SubReg carries the "Kill" flag when SubReg == SuperReg. 691 unsigned SubKillState = getKillRegState((NumSubRegs == 1) && IsKill); 692 for (unsigned i = 0, e = NumSubRegs; i < e; ++i) { 693 unsigned SubReg = NumSubRegs == 1 ? 694 SuperReg : getSubReg(SuperReg, SplitParts[i]); 695 696 if (SpillToSMEM) { 697 int64_t FrOffset = FrameInfo.getObjectOffset(Index); 698 699 // The allocated memory size is really the wavefront size * the frame 700 // index size. The widest register class is 64 bytes, so a 4-byte scratch 701 // allocation is enough to spill this in a single stack object. 702 // 703 // FIXME: Frame size/offsets are computed earlier than this, so the extra 704 // space is still unnecessarily allocated. 705 706 unsigned Align = FrameInfo.getObjectAlignment(Index); 707 MachinePointerInfo PtrInfo 708 = MachinePointerInfo::getFixedStack(*MF, Index, EltSize * i); 709 MachineMemOperand *MMO 710 = MF->getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore, 711 EltSize, MinAlign(Align, EltSize * i)); 712 713 // SMEM instructions only support a single offset, so increment the wave 714 // offset. 715 716 int64_t Offset = (ST.getWavefrontSize() * FrOffset) + (EltSize * i); 717 if (Offset != 0) { 718 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_ADD_U32), OffsetReg) 719 .addReg(MFI->getFrameOffsetReg()) 720 .addImm(Offset); 721 } else { 722 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), OffsetReg) 723 .addReg(MFI->getFrameOffsetReg()); 724 } 725 726 BuildMI(*MBB, MI, DL, TII->get(ScalarStoreOp)) 727 .addReg(SubReg, getKillRegState(IsKill)) // sdata 728 .addReg(MFI->getScratchRSrcReg()) // sbase 729 .addReg(OffsetReg, RegState::Kill) // soff 730 .addImm(0) // glc 731 .addMemOperand(MMO); 732 733 continue; 734 } 735 736 if (SpillToVGPR) { 737 SIMachineFunctionInfo::SpilledReg Spill = VGPRSpills[i]; 738 739 BuildMI(*MBB, MI, DL, 740 TII->getMCOpcodeFromPseudo(AMDGPU::V_WRITELANE_B32), 741 Spill.VGPR) 742 .addReg(SubReg, getKillRegState(IsKill)) 743 .addImm(Spill.Lane); 744 745 // FIXME: Since this spills to another register instead of an actual 746 // frame index, we should delete the frame index when all references to 747 // it are fixed. 748 } else { 749 // XXX - Can to VGPR spill fail for some subregisters but not others? 750 if (OnlyToVGPR) 751 return false; 752 753 // Spill SGPR to a frame index. 754 // TODO: Should VI try to spill to VGPR and then spill to SMEM? 755 unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 756 // TODO: Should VI try to spill to VGPR and then spill to SMEM? 757 758 MachineInstrBuilder Mov 759 = BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), TmpReg) 760 .addReg(SubReg, SubKillState); 761 762 763 // There could be undef components of a spilled super register. 764 // TODO: Can we detect this and skip the spill? 765 if (NumSubRegs > 1) { 766 // The last implicit use of the SuperReg carries the "Kill" flag. 767 unsigned SuperKillState = 0; 768 if (i + 1 == e) 769 SuperKillState |= getKillRegState(IsKill); 770 Mov.addReg(SuperReg, RegState::Implicit | SuperKillState); 771 } 772 773 unsigned Align = FrameInfo.getObjectAlignment(Index); 774 MachinePointerInfo PtrInfo 775 = MachinePointerInfo::getFixedStack(*MF, Index, EltSize * i); 776 MachineMemOperand *MMO 777 = MF->getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore, 778 EltSize, MinAlign(Align, EltSize * i)); 779 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::SI_SPILL_V32_SAVE)) 780 .addReg(TmpReg, RegState::Kill) // src 781 .addFrameIndex(Index) // vaddr 782 .addReg(MFI->getScratchRSrcReg()) // srrsrc 783 .addReg(MFI->getFrameOffsetReg()) // soffset 784 .addImm(i * 4) // offset 785 .addMemOperand(MMO); 786 } 787 } 788 789 if (M0CopyReg != AMDGPU::NoRegister) { 790 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::COPY), AMDGPU::M0) 791 .addReg(M0CopyReg, RegState::Kill); 792 } 793 794 MI->eraseFromParent(); 795 MFI->addToSpilledSGPRs(NumSubRegs); 796 return true; 797 } 798 799 bool SIRegisterInfo::restoreSGPR(MachineBasicBlock::iterator MI, 800 int Index, 801 RegScavenger *RS, 802 bool OnlyToVGPR) const { 803 MachineFunction *MF = MI->getParent()->getParent(); 804 MachineRegisterInfo &MRI = MF->getRegInfo(); 805 MachineBasicBlock *MBB = MI->getParent(); 806 SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>(); 807 808 ArrayRef<SIMachineFunctionInfo::SpilledReg> VGPRSpills 809 = MFI->getSGPRToVGPRSpills(Index); 810 bool SpillToVGPR = !VGPRSpills.empty(); 811 if (OnlyToVGPR && !SpillToVGPR) 812 return false; 813 814 MachineFrameInfo &FrameInfo = MF->getFrameInfo(); 815 const SISubtarget &ST = MF->getSubtarget<SISubtarget>(); 816 const SIInstrInfo *TII = ST.getInstrInfo(); 817 const DebugLoc &DL = MI->getDebugLoc(); 818 819 unsigned SuperReg = MI->getOperand(0).getReg(); 820 bool SpillToSMEM = spillSGPRToSMEM(); 821 if (SpillToSMEM && OnlyToVGPR) 822 return false; 823 824 assert(SuperReg != AMDGPU::M0 && "m0 should never spill"); 825 826 unsigned OffsetReg = AMDGPU::M0; 827 unsigned M0CopyReg = AMDGPU::NoRegister; 828 829 if (SpillToSMEM) { 830 if (RS->isRegUsed(AMDGPU::M0)) { 831 M0CopyReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 832 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::COPY), M0CopyReg) 833 .addReg(AMDGPU::M0); 834 } 835 } 836 837 unsigned EltSize = 4; 838 unsigned ScalarLoadOp; 839 840 const TargetRegisterClass *RC = getPhysRegClass(SuperReg); 841 if (SpillToSMEM && isSGPRClass(RC)) { 842 // XXX - if private_element_size is larger than 4 it might be useful to be 843 // able to spill wider vmem spills. 844 std::tie(EltSize, ScalarLoadOp) = 845 getSpillEltSize(getRegSizeInBits(*RC) / 8, false); 846 } 847 848 ArrayRef<int16_t> SplitParts = getRegSplitParts(RC, EltSize); 849 unsigned NumSubRegs = SplitParts.empty() ? 1 : SplitParts.size(); 850 851 // SubReg carries the "Kill" flag when SubReg == SuperReg. 852 int64_t FrOffset = FrameInfo.getObjectOffset(Index); 853 854 for (unsigned i = 0, e = NumSubRegs; i < e; ++i) { 855 unsigned SubReg = NumSubRegs == 1 ? 856 SuperReg : getSubReg(SuperReg, SplitParts[i]); 857 858 if (SpillToSMEM) { 859 // FIXME: Size may be > 4 but extra bytes wasted. 860 unsigned Align = FrameInfo.getObjectAlignment(Index); 861 MachinePointerInfo PtrInfo 862 = MachinePointerInfo::getFixedStack(*MF, Index, EltSize * i); 863 MachineMemOperand *MMO 864 = MF->getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad, 865 EltSize, MinAlign(Align, EltSize * i)); 866 867 // Add i * 4 offset 868 int64_t Offset = (ST.getWavefrontSize() * FrOffset) + (EltSize * i); 869 if (Offset != 0) { 870 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_ADD_U32), OffsetReg) 871 .addReg(MFI->getFrameOffsetReg()) 872 .addImm(Offset); 873 } else { 874 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), OffsetReg) 875 .addReg(MFI->getFrameOffsetReg()); 876 } 877 878 auto MIB = 879 BuildMI(*MBB, MI, DL, TII->get(ScalarLoadOp), SubReg) 880 .addReg(MFI->getScratchRSrcReg()) // sbase 881 .addReg(OffsetReg, RegState::Kill) // soff 882 .addImm(0) // glc 883 .addMemOperand(MMO); 884 885 if (NumSubRegs > 1) 886 MIB.addReg(SuperReg, RegState::ImplicitDefine); 887 888 continue; 889 } 890 891 if (SpillToVGPR) { 892 SIMachineFunctionInfo::SpilledReg Spill = VGPRSpills[i]; 893 auto MIB = 894 BuildMI(*MBB, MI, DL, TII->getMCOpcodeFromPseudo(AMDGPU::V_READLANE_B32), 895 SubReg) 896 .addReg(Spill.VGPR) 897 .addImm(Spill.Lane); 898 899 if (NumSubRegs > 1) 900 MIB.addReg(SuperReg, RegState::ImplicitDefine); 901 } else { 902 if (OnlyToVGPR) 903 return false; 904 905 // Restore SGPR from a stack slot. 906 // FIXME: We should use S_LOAD_DWORD here for VI. 907 unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 908 unsigned Align = FrameInfo.getObjectAlignment(Index); 909 910 MachinePointerInfo PtrInfo 911 = MachinePointerInfo::getFixedStack(*MF, Index, EltSize * i); 912 913 MachineMemOperand *MMO = MF->getMachineMemOperand(PtrInfo, 914 MachineMemOperand::MOLoad, EltSize, 915 MinAlign(Align, EltSize * i)); 916 917 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::SI_SPILL_V32_RESTORE), TmpReg) 918 .addFrameIndex(Index) // vaddr 919 .addReg(MFI->getScratchRSrcReg()) // srsrc 920 .addReg(MFI->getFrameOffsetReg()) // soffset 921 .addImm(i * 4) // offset 922 .addMemOperand(MMO); 923 924 auto MIB = 925 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), SubReg) 926 .addReg(TmpReg, RegState::Kill); 927 928 if (NumSubRegs > 1) 929 MIB.addReg(MI->getOperand(0).getReg(), RegState::ImplicitDefine); 930 } 931 } 932 933 if (M0CopyReg != AMDGPU::NoRegister) { 934 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::COPY), AMDGPU::M0) 935 .addReg(M0CopyReg, RegState::Kill); 936 } 937 938 MI->eraseFromParent(); 939 return true; 940 } 941 942 /// Special case of eliminateFrameIndex. Returns true if the SGPR was spilled to 943 /// a VGPR and the stack slot can be safely eliminated when all other users are 944 /// handled. 945 bool SIRegisterInfo::eliminateSGPRToVGPRSpillFrameIndex( 946 MachineBasicBlock::iterator MI, 947 int FI, 948 RegScavenger *RS) const { 949 switch (MI->getOpcode()) { 950 case AMDGPU::SI_SPILL_S512_SAVE: 951 case AMDGPU::SI_SPILL_S256_SAVE: 952 case AMDGPU::SI_SPILL_S128_SAVE: 953 case AMDGPU::SI_SPILL_S64_SAVE: 954 case AMDGPU::SI_SPILL_S32_SAVE: 955 return spillSGPR(MI, FI, RS, true); 956 case AMDGPU::SI_SPILL_S512_RESTORE: 957 case AMDGPU::SI_SPILL_S256_RESTORE: 958 case AMDGPU::SI_SPILL_S128_RESTORE: 959 case AMDGPU::SI_SPILL_S64_RESTORE: 960 case AMDGPU::SI_SPILL_S32_RESTORE: 961 return restoreSGPR(MI, FI, RS, true); 962 default: 963 llvm_unreachable("not an SGPR spill instruction"); 964 } 965 } 966 967 void SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI, 968 int SPAdj, unsigned FIOperandNum, 969 RegScavenger *RS) const { 970 MachineFunction *MF = MI->getParent()->getParent(); 971 MachineRegisterInfo &MRI = MF->getRegInfo(); 972 MachineBasicBlock *MBB = MI->getParent(); 973 SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>(); 974 MachineFrameInfo &FrameInfo = MF->getFrameInfo(); 975 const SISubtarget &ST = MF->getSubtarget<SISubtarget>(); 976 const SIInstrInfo *TII = ST.getInstrInfo(); 977 DebugLoc DL = MI->getDebugLoc(); 978 979 MachineOperand &FIOp = MI->getOperand(FIOperandNum); 980 int Index = MI->getOperand(FIOperandNum).getIndex(); 981 982 switch (MI->getOpcode()) { 983 // SGPR register spill 984 case AMDGPU::SI_SPILL_S512_SAVE: 985 case AMDGPU::SI_SPILL_S256_SAVE: 986 case AMDGPU::SI_SPILL_S128_SAVE: 987 case AMDGPU::SI_SPILL_S64_SAVE: 988 case AMDGPU::SI_SPILL_S32_SAVE: { 989 spillSGPR(MI, Index, RS); 990 break; 991 } 992 993 // SGPR register restore 994 case AMDGPU::SI_SPILL_S512_RESTORE: 995 case AMDGPU::SI_SPILL_S256_RESTORE: 996 case AMDGPU::SI_SPILL_S128_RESTORE: 997 case AMDGPU::SI_SPILL_S64_RESTORE: 998 case AMDGPU::SI_SPILL_S32_RESTORE: { 999 restoreSGPR(MI, Index, RS); 1000 break; 1001 } 1002 1003 // VGPR register spill 1004 case AMDGPU::SI_SPILL_V512_SAVE: 1005 case AMDGPU::SI_SPILL_V256_SAVE: 1006 case AMDGPU::SI_SPILL_V128_SAVE: 1007 case AMDGPU::SI_SPILL_V96_SAVE: 1008 case AMDGPU::SI_SPILL_V64_SAVE: 1009 case AMDGPU::SI_SPILL_V32_SAVE: { 1010 const MachineOperand *VData = TII->getNamedOperand(*MI, 1011 AMDGPU::OpName::vdata); 1012 buildSpillLoadStore(MI, AMDGPU::BUFFER_STORE_DWORD_OFFSET, 1013 Index, 1014 VData->getReg(), VData->isKill(), 1015 TII->getNamedOperand(*MI, AMDGPU::OpName::srsrc)->getReg(), 1016 TII->getNamedOperand(*MI, AMDGPU::OpName::soffset)->getReg(), 1017 TII->getNamedOperand(*MI, AMDGPU::OpName::offset)->getImm(), 1018 *MI->memoperands_begin(), 1019 RS); 1020 MFI->addToSpilledVGPRs(getNumSubRegsForSpillOp(MI->getOpcode())); 1021 MI->eraseFromParent(); 1022 break; 1023 } 1024 case AMDGPU::SI_SPILL_V32_RESTORE: 1025 case AMDGPU::SI_SPILL_V64_RESTORE: 1026 case AMDGPU::SI_SPILL_V96_RESTORE: 1027 case AMDGPU::SI_SPILL_V128_RESTORE: 1028 case AMDGPU::SI_SPILL_V256_RESTORE: 1029 case AMDGPU::SI_SPILL_V512_RESTORE: { 1030 const MachineOperand *VData = TII->getNamedOperand(*MI, 1031 AMDGPU::OpName::vdata); 1032 1033 buildSpillLoadStore(MI, AMDGPU::BUFFER_LOAD_DWORD_OFFSET, 1034 Index, 1035 VData->getReg(), VData->isKill(), 1036 TII->getNamedOperand(*MI, AMDGPU::OpName::srsrc)->getReg(), 1037 TII->getNamedOperand(*MI, AMDGPU::OpName::soffset)->getReg(), 1038 TII->getNamedOperand(*MI, AMDGPU::OpName::offset)->getImm(), 1039 *MI->memoperands_begin(), 1040 RS); 1041 MI->eraseFromParent(); 1042 break; 1043 } 1044 1045 default: { 1046 const DebugLoc &DL = MI->getDebugLoc(); 1047 bool IsMUBUF = TII->isMUBUF(*MI); 1048 1049 if (!IsMUBUF && 1050 MFI->getFrameOffsetReg() != MFI->getScratchWaveOffsetReg()) { 1051 // Convert to an absolute stack address by finding the offset from the 1052 // scratch wave base and scaling by the wave size. 1053 // 1054 // In an entry function/kernel the stack address is already the absolute 1055 // address relative to the the scratch wave offset. 1056 1057 unsigned DiffReg 1058 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 1059 1060 bool IsCopy = MI->getOpcode() == AMDGPU::V_MOV_B32_e32; 1061 unsigned ResultReg = IsCopy ? 1062 MI->getOperand(0).getReg() : 1063 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 1064 1065 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_SUB_U32), DiffReg) 1066 .addReg(MFI->getFrameOffsetReg()) 1067 .addReg(MFI->getScratchWaveOffsetReg()); 1068 1069 int64_t Offset = FrameInfo.getObjectOffset(Index); 1070 if (Offset == 0) { 1071 // XXX - This never happens because of emergency scavenging slot at 0? 1072 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_LSHRREV_B32_e64), ResultReg) 1073 .addImm(Log2_32(ST.getWavefrontSize())) 1074 .addReg(DiffReg); 1075 } else { 1076 unsigned ScaledReg 1077 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 1078 1079 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_LSHRREV_B32_e64), ScaledReg) 1080 .addImm(Log2_32(ST.getWavefrontSize())) 1081 .addReg(DiffReg, RegState::Kill); 1082 1083 // TODO: Fold if use instruction is another add of a constant. 1084 if (AMDGPU::isInlinableLiteral32(Offset, ST.hasInv2PiInlineImm())) { 1085 TII->getAddNoCarry(*MBB, MI, DL, ResultReg) 1086 .addImm(Offset) 1087 .addReg(ScaledReg, RegState::Kill); 1088 } else { 1089 unsigned ConstOffsetReg 1090 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 1091 1092 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), ConstOffsetReg) 1093 .addImm(Offset); 1094 TII->getAddNoCarry(*MBB, MI, DL, ResultReg) 1095 .addReg(ConstOffsetReg, RegState::Kill) 1096 .addReg(ScaledReg, RegState::Kill); 1097 } 1098 } 1099 1100 // Don't introduce an extra copy if we're just materializing in a mov. 1101 if (IsCopy) 1102 MI->eraseFromParent(); 1103 else 1104 FIOp.ChangeToRegister(ResultReg, false, false, true); 1105 return; 1106 } 1107 1108 if (IsMUBUF) { 1109 // Disable offen so we don't need a 0 vgpr base. 1110 assert(static_cast<int>(FIOperandNum) == 1111 AMDGPU::getNamedOperandIdx(MI->getOpcode(), 1112 AMDGPU::OpName::vaddr)); 1113 1114 assert(TII->getNamedOperand(*MI, AMDGPU::OpName::soffset)->getReg() 1115 == MFI->getFrameOffsetReg()); 1116 1117 int64_t Offset = FrameInfo.getObjectOffset(Index); 1118 int64_t OldImm 1119 = TII->getNamedOperand(*MI, AMDGPU::OpName::offset)->getImm(); 1120 int64_t NewOffset = OldImm + Offset; 1121 1122 if (isUInt<12>(NewOffset) && 1123 buildMUBUFOffsetLoadStore(TII, FrameInfo, MI, Index, NewOffset)) { 1124 MI->eraseFromParent(); 1125 return; 1126 } 1127 } 1128 1129 // If the offset is simply too big, don't convert to a scratch wave offset 1130 // relative index. 1131 1132 int64_t Offset = FrameInfo.getObjectOffset(Index); 1133 FIOp.ChangeToImmediate(Offset); 1134 if (!TII->isImmOperandLegal(*MI, FIOperandNum, FIOp)) { 1135 unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 1136 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), TmpReg) 1137 .addImm(Offset); 1138 FIOp.ChangeToRegister(TmpReg, false, false, true); 1139 } 1140 } 1141 } 1142 } 1143 1144 StringRef SIRegisterInfo::getRegAsmName(unsigned Reg) const { 1145 #define AMDGPU_REG_ASM_NAMES 1146 #include "AMDGPURegAsmNames.inc.cpp" 1147 1148 #define REG_RANGE(BeginReg, EndReg, RegTable) \ 1149 if (Reg >= BeginReg && Reg <= EndReg) { \ 1150 unsigned Index = Reg - BeginReg; \ 1151 assert(Index < array_lengthof(RegTable)); \ 1152 return RegTable[Index]; \ 1153 } 1154 1155 REG_RANGE(AMDGPU::VGPR0, AMDGPU::VGPR255, VGPR32RegNames); 1156 REG_RANGE(AMDGPU::SGPR0, AMDGPU::SGPR103, SGPR32RegNames); 1157 REG_RANGE(AMDGPU::VGPR0_VGPR1, AMDGPU::VGPR254_VGPR255, VGPR64RegNames); 1158 REG_RANGE(AMDGPU::SGPR0_SGPR1, AMDGPU::SGPR102_SGPR103, SGPR64RegNames); 1159 REG_RANGE(AMDGPU::VGPR0_VGPR1_VGPR2, AMDGPU::VGPR253_VGPR254_VGPR255, 1160 VGPR96RegNames); 1161 1162 REG_RANGE(AMDGPU::VGPR0_VGPR1_VGPR2_VGPR3, 1163 AMDGPU::VGPR252_VGPR253_VGPR254_VGPR255, 1164 VGPR128RegNames); 1165 REG_RANGE(AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3, 1166 AMDGPU::SGPR100_SGPR101_SGPR102_SGPR103, 1167 SGPR128RegNames); 1168 1169 REG_RANGE(AMDGPU::VGPR0_VGPR1_VGPR2_VGPR3_VGPR4_VGPR5_VGPR6_VGPR7, 1170 AMDGPU::VGPR248_VGPR249_VGPR250_VGPR251_VGPR252_VGPR253_VGPR254_VGPR255, 1171 VGPR256RegNames); 1172 1173 REG_RANGE( 1174 AMDGPU::VGPR0_VGPR1_VGPR2_VGPR3_VGPR4_VGPR5_VGPR6_VGPR7_VGPR8_VGPR9_VGPR10_VGPR11_VGPR12_VGPR13_VGPR14_VGPR15, 1175 AMDGPU::VGPR240_VGPR241_VGPR242_VGPR243_VGPR244_VGPR245_VGPR246_VGPR247_VGPR248_VGPR249_VGPR250_VGPR251_VGPR252_VGPR253_VGPR254_VGPR255, 1176 VGPR512RegNames); 1177 1178 REG_RANGE(AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3_SGPR4_SGPR5_SGPR6_SGPR7, 1179 AMDGPU::SGPR96_SGPR97_SGPR98_SGPR99_SGPR100_SGPR101_SGPR102_SGPR103, 1180 SGPR256RegNames); 1181 1182 REG_RANGE( 1183 AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3_SGPR4_SGPR5_SGPR6_SGPR7_SGPR8_SGPR9_SGPR10_SGPR11_SGPR12_SGPR13_SGPR14_SGPR15, 1184 AMDGPU::SGPR88_SGPR89_SGPR90_SGPR91_SGPR92_SGPR93_SGPR94_SGPR95_SGPR96_SGPR97_SGPR98_SGPR99_SGPR100_SGPR101_SGPR102_SGPR103, 1185 SGPR512RegNames 1186 ); 1187 1188 #undef REG_RANGE 1189 1190 // FIXME: Rename flat_scr so we don't need to special case this. 1191 switch (Reg) { 1192 case AMDGPU::FLAT_SCR: 1193 return "flat_scratch"; 1194 case AMDGPU::FLAT_SCR_LO: 1195 return "flat_scratch_lo"; 1196 case AMDGPU::FLAT_SCR_HI: 1197 return "flat_scratch_hi"; 1198 default: 1199 // For the special named registers the default is fine. 1200 return TargetRegisterInfo::getRegAsmName(Reg); 1201 } 1202 } 1203 1204 // FIXME: This is very slow. It might be worth creating a map from physreg to 1205 // register class. 1206 const TargetRegisterClass *SIRegisterInfo::getPhysRegClass(unsigned Reg) const { 1207 assert(!TargetRegisterInfo::isVirtualRegister(Reg)); 1208 1209 static const TargetRegisterClass *const BaseClasses[] = { 1210 &AMDGPU::VGPR_32RegClass, 1211 &AMDGPU::SReg_32RegClass, 1212 &AMDGPU::VReg_64RegClass, 1213 &AMDGPU::SReg_64RegClass, 1214 &AMDGPU::VReg_96RegClass, 1215 &AMDGPU::VReg_128RegClass, 1216 &AMDGPU::SReg_128RegClass, 1217 &AMDGPU::VReg_256RegClass, 1218 &AMDGPU::SReg_256RegClass, 1219 &AMDGPU::VReg_512RegClass, 1220 &AMDGPU::SReg_512RegClass, 1221 &AMDGPU::SCC_CLASSRegClass, 1222 }; 1223 1224 for (const TargetRegisterClass *BaseClass : BaseClasses) { 1225 if (BaseClass->contains(Reg)) { 1226 return BaseClass; 1227 } 1228 } 1229 return nullptr; 1230 } 1231 1232 // TODO: It might be helpful to have some target specific flags in 1233 // TargetRegisterClass to mark which classes are VGPRs to make this trivial. 1234 bool SIRegisterInfo::hasVGPRs(const TargetRegisterClass *RC) const { 1235 unsigned Size = getRegSizeInBits(*RC); 1236 if (Size < 32) 1237 return false; 1238 switch (Size) { 1239 case 32: 1240 return getCommonSubClass(&AMDGPU::VGPR_32RegClass, RC) != nullptr; 1241 case 64: 1242 return getCommonSubClass(&AMDGPU::VReg_64RegClass, RC) != nullptr; 1243 case 96: 1244 return getCommonSubClass(&AMDGPU::VReg_96RegClass, RC) != nullptr; 1245 case 128: 1246 return getCommonSubClass(&AMDGPU::VReg_128RegClass, RC) != nullptr; 1247 case 256: 1248 return getCommonSubClass(&AMDGPU::VReg_256RegClass, RC) != nullptr; 1249 case 512: 1250 return getCommonSubClass(&AMDGPU::VReg_512RegClass, RC) != nullptr; 1251 default: 1252 llvm_unreachable("Invalid register class size"); 1253 } 1254 } 1255 1256 const TargetRegisterClass *SIRegisterInfo::getEquivalentVGPRClass( 1257 const TargetRegisterClass *SRC) const { 1258 switch (getRegSizeInBits(*SRC)) { 1259 case 32: 1260 return &AMDGPU::VGPR_32RegClass; 1261 case 64: 1262 return &AMDGPU::VReg_64RegClass; 1263 case 96: 1264 return &AMDGPU::VReg_96RegClass; 1265 case 128: 1266 return &AMDGPU::VReg_128RegClass; 1267 case 256: 1268 return &AMDGPU::VReg_256RegClass; 1269 case 512: 1270 return &AMDGPU::VReg_512RegClass; 1271 default: 1272 llvm_unreachable("Invalid register class size"); 1273 } 1274 } 1275 1276 const TargetRegisterClass *SIRegisterInfo::getEquivalentSGPRClass( 1277 const TargetRegisterClass *VRC) const { 1278 switch (getRegSizeInBits(*VRC)) { 1279 case 32: 1280 return &AMDGPU::SGPR_32RegClass; 1281 case 64: 1282 return &AMDGPU::SReg_64RegClass; 1283 case 128: 1284 return &AMDGPU::SReg_128RegClass; 1285 case 256: 1286 return &AMDGPU::SReg_256RegClass; 1287 case 512: 1288 return &AMDGPU::SReg_512RegClass; 1289 default: 1290 llvm_unreachable("Invalid register class size"); 1291 } 1292 } 1293 1294 const TargetRegisterClass *SIRegisterInfo::getSubRegClass( 1295 const TargetRegisterClass *RC, unsigned SubIdx) const { 1296 if (SubIdx == AMDGPU::NoSubRegister) 1297 return RC; 1298 1299 // We can assume that each lane corresponds to one 32-bit register. 1300 unsigned Count = getSubRegIndexLaneMask(SubIdx).getNumLanes(); 1301 if (isSGPRClass(RC)) { 1302 switch (Count) { 1303 case 1: 1304 return &AMDGPU::SGPR_32RegClass; 1305 case 2: 1306 return &AMDGPU::SReg_64RegClass; 1307 case 4: 1308 return &AMDGPU::SReg_128RegClass; 1309 case 8: 1310 return &AMDGPU::SReg_256RegClass; 1311 case 16: /* fall-through */ 1312 default: 1313 llvm_unreachable("Invalid sub-register class size"); 1314 } 1315 } else { 1316 switch (Count) { 1317 case 1: 1318 return &AMDGPU::VGPR_32RegClass; 1319 case 2: 1320 return &AMDGPU::VReg_64RegClass; 1321 case 3: 1322 return &AMDGPU::VReg_96RegClass; 1323 case 4: 1324 return &AMDGPU::VReg_128RegClass; 1325 case 8: 1326 return &AMDGPU::VReg_256RegClass; 1327 case 16: /* fall-through */ 1328 default: 1329 llvm_unreachable("Invalid sub-register class size"); 1330 } 1331 } 1332 } 1333 1334 bool SIRegisterInfo::shouldRewriteCopySrc( 1335 const TargetRegisterClass *DefRC, 1336 unsigned DefSubReg, 1337 const TargetRegisterClass *SrcRC, 1338 unsigned SrcSubReg) const { 1339 // We want to prefer the smallest register class possible, so we don't want to 1340 // stop and rewrite on anything that looks like a subregister 1341 // extract. Operations mostly don't care about the super register class, so we 1342 // only want to stop on the most basic of copies between the same register 1343 // class. 1344 // 1345 // e.g. if we have something like 1346 // %0 = ... 1347 // %1 = ... 1348 // %2 = REG_SEQUENCE %0, sub0, %1, sub1, %2, sub2 1349 // %3 = COPY %2, sub0 1350 // 1351 // We want to look through the COPY to find: 1352 // => %3 = COPY %0 1353 1354 // Plain copy. 1355 return getCommonSubClass(DefRC, SrcRC) != nullptr; 1356 } 1357 1358 /// \brief Returns a register that is not used at any point in the function. 1359 /// If all registers are used, then this function will return 1360 // AMDGPU::NoRegister. 1361 unsigned 1362 SIRegisterInfo::findUnusedRegister(const MachineRegisterInfo &MRI, 1363 const TargetRegisterClass *RC, 1364 const MachineFunction &MF) const { 1365 1366 for (unsigned Reg : *RC) 1367 if (MRI.isAllocatable(Reg) && !MRI.isPhysRegUsed(Reg)) 1368 return Reg; 1369 return AMDGPU::NoRegister; 1370 } 1371 1372 ArrayRef<int16_t> SIRegisterInfo::getRegSplitParts(const TargetRegisterClass *RC, 1373 unsigned EltSize) const { 1374 if (EltSize == 4) { 1375 static const int16_t Sub0_15[] = { 1376 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3, 1377 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7, 1378 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11, 1379 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15, 1380 }; 1381 1382 static const int16_t Sub0_7[] = { 1383 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3, 1384 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7, 1385 }; 1386 1387 static const int16_t Sub0_3[] = { 1388 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3, 1389 }; 1390 1391 static const int16_t Sub0_2[] = { 1392 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, 1393 }; 1394 1395 static const int16_t Sub0_1[] = { 1396 AMDGPU::sub0, AMDGPU::sub1, 1397 }; 1398 1399 switch (AMDGPU::getRegBitWidth(*RC->MC)) { 1400 case 32: 1401 return {}; 1402 case 64: 1403 return makeArrayRef(Sub0_1); 1404 case 96: 1405 return makeArrayRef(Sub0_2); 1406 case 128: 1407 return makeArrayRef(Sub0_3); 1408 case 256: 1409 return makeArrayRef(Sub0_7); 1410 case 512: 1411 return makeArrayRef(Sub0_15); 1412 default: 1413 llvm_unreachable("unhandled register size"); 1414 } 1415 } 1416 1417 if (EltSize == 8) { 1418 static const int16_t Sub0_15_64[] = { 1419 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3, 1420 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7, 1421 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11, 1422 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15 1423 }; 1424 1425 static const int16_t Sub0_7_64[] = { 1426 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3, 1427 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7 1428 }; 1429 1430 1431 static const int16_t Sub0_3_64[] = { 1432 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3 1433 }; 1434 1435 switch (AMDGPU::getRegBitWidth(*RC->MC)) { 1436 case 64: 1437 return {}; 1438 case 128: 1439 return makeArrayRef(Sub0_3_64); 1440 case 256: 1441 return makeArrayRef(Sub0_7_64); 1442 case 512: 1443 return makeArrayRef(Sub0_15_64); 1444 default: 1445 llvm_unreachable("unhandled register size"); 1446 } 1447 } 1448 1449 assert(EltSize == 16 && "unhandled register spill split size"); 1450 1451 static const int16_t Sub0_15_128[] = { 1452 AMDGPU::sub0_sub1_sub2_sub3, 1453 AMDGPU::sub4_sub5_sub6_sub7, 1454 AMDGPU::sub8_sub9_sub10_sub11, 1455 AMDGPU::sub12_sub13_sub14_sub15 1456 }; 1457 1458 static const int16_t Sub0_7_128[] = { 1459 AMDGPU::sub0_sub1_sub2_sub3, 1460 AMDGPU::sub4_sub5_sub6_sub7 1461 }; 1462 1463 switch (AMDGPU::getRegBitWidth(*RC->MC)) { 1464 case 128: 1465 return {}; 1466 case 256: 1467 return makeArrayRef(Sub0_7_128); 1468 case 512: 1469 return makeArrayRef(Sub0_15_128); 1470 default: 1471 llvm_unreachable("unhandled register size"); 1472 } 1473 } 1474 1475 const TargetRegisterClass* 1476 SIRegisterInfo::getRegClassForReg(const MachineRegisterInfo &MRI, 1477 unsigned Reg) const { 1478 if (TargetRegisterInfo::isVirtualRegister(Reg)) 1479 return MRI.getRegClass(Reg); 1480 1481 return getPhysRegClass(Reg); 1482 } 1483 1484 bool SIRegisterInfo::isVGPR(const MachineRegisterInfo &MRI, 1485 unsigned Reg) const { 1486 return hasVGPRs(getRegClassForReg(MRI, Reg)); 1487 } 1488 1489 bool SIRegisterInfo::shouldCoalesce(MachineInstr *MI, 1490 const TargetRegisterClass *SrcRC, 1491 unsigned SubReg, 1492 const TargetRegisterClass *DstRC, 1493 unsigned DstSubReg, 1494 const TargetRegisterClass *NewRC, 1495 LiveIntervals &LIS) const { 1496 unsigned SrcSize = getRegSizeInBits(*SrcRC); 1497 unsigned DstSize = getRegSizeInBits(*DstRC); 1498 unsigned NewSize = getRegSizeInBits(*NewRC); 1499 1500 // Do not increase size of registers beyond dword, we would need to allocate 1501 // adjacent registers and constraint regalloc more than needed. 1502 1503 // Always allow dword coalescing. 1504 if (SrcSize <= 32 || DstSize <= 32) 1505 return true; 1506 1507 return NewSize <= DstSize || NewSize <= SrcSize; 1508 } 1509 1510 unsigned SIRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, 1511 MachineFunction &MF) const { 1512 1513 const SISubtarget &ST = MF.getSubtarget<SISubtarget>(); 1514 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>(); 1515 1516 unsigned Occupancy = ST.getOccupancyWithLocalMemSize(MFI->getLDSSize(), 1517 MF.getFunction()); 1518 switch (RC->getID()) { 1519 default: 1520 return AMDGPURegisterInfo::getRegPressureLimit(RC, MF); 1521 case AMDGPU::VGPR_32RegClassID: 1522 return std::min(ST.getMaxNumVGPRs(Occupancy), ST.getMaxNumVGPRs(MF)); 1523 case AMDGPU::SGPR_32RegClassID: 1524 return std::min(ST.getMaxNumSGPRs(Occupancy, true), ST.getMaxNumSGPRs(MF)); 1525 } 1526 } 1527 1528 unsigned SIRegisterInfo::getRegPressureSetLimit(const MachineFunction &MF, 1529 unsigned Idx) const { 1530 if (Idx == getVGPRPressureSet()) 1531 return getRegPressureLimit(&AMDGPU::VGPR_32RegClass, 1532 const_cast<MachineFunction &>(MF)); 1533 1534 if (Idx == getSGPRPressureSet()) 1535 return getRegPressureLimit(&AMDGPU::SGPR_32RegClass, 1536 const_cast<MachineFunction &>(MF)); 1537 1538 return AMDGPURegisterInfo::getRegPressureSetLimit(MF, Idx); 1539 } 1540 1541 const int *SIRegisterInfo::getRegUnitPressureSets(unsigned RegUnit) const { 1542 static const int Empty[] = { -1 }; 1543 1544 if (hasRegUnit(AMDGPU::M0, RegUnit)) 1545 return Empty; 1546 return AMDGPURegisterInfo::getRegUnitPressureSets(RegUnit); 1547 } 1548