diff options
Diffstat (limited to 'llvm/lib/Target/R600/SIInstrInfo.cpp')
| -rw-r--r-- | llvm/lib/Target/R600/SIInstrInfo.cpp | 36 |
1 files changed, 23 insertions, 13 deletions
diff --git a/llvm/lib/Target/R600/SIInstrInfo.cpp b/llvm/lib/Target/R600/SIInstrInfo.cpp index 44e47e53b1e..42f10f21f98 100644 --- a/llvm/lib/Target/R600/SIInstrInfo.cpp +++ b/llvm/lib/Target/R600/SIInstrInfo.cpp @@ -971,15 +971,19 @@ bool SIInstrInfo::isImmOperandLegal(const MachineInstr *MI, unsigned OpNo, return RI.regClassCanUseInlineConstant(OpInfo.RegClass); } -bool SIInstrInfo::canFoldOffset(unsigned OffsetSize, unsigned AS) { +bool SIInstrInfo::canFoldOffset(unsigned OffsetSize, unsigned AS) const { switch (AS) { case AMDGPUAS::GLOBAL_ADDRESS: { // MUBUF instructions a 12-bit offset in bytes. return isUInt<12>(OffsetSize); } case AMDGPUAS::CONSTANT_ADDRESS: { - // SMRD instructions have an 8-bit offset in dwords. - return (OffsetSize % 4 == 0) && isUInt<8>(OffsetSize / 4); + // SMRD instructions have an 8-bit offset in dwords on SI and + // a 20-bit offset in bytes on VI. + if (RI.ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS) + return isUInt<20>(OffsetSize); + else + return (OffsetSize % 4 == 0) && isUInt<8>(OffsetSize / 4); } case AMDGPUAS::LOCAL_ADDRESS: case AMDGPUAS::REGION_ADDRESS: { @@ -1701,27 +1705,30 @@ void SIInstrInfo::splitSMRD(MachineInstr *MI, getNamedOperand(*MI, AMDGPU::OpName::offset); const MachineOperand *SBase = getNamedOperand(*MI, AMDGPU::OpName::sbase); + // The SMRD has an 8-bit offset in dwords on SI and a 20-bit offset in bytes + // on VI. if (OffOp) { + bool isVI = RI.ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS; + unsigned OffScale = isVI ? 1 : 4; // Handle the _IMM variant - unsigned LoOffset = OffOp->getImm(); - unsigned HiOffset = LoOffset + (HalfSize / 4); + unsigned LoOffset = OffOp->getImm() * OffScale; + unsigned HiOffset = LoOffset + HalfSize; Lo = BuildMI(*MBB, MI, DL, get(HalfImmOp), RegLo) .addOperand(*SBase) - .addImm(LoOffset); + .addImm(LoOffset / OffScale); - if (!isUInt<8>(HiOffset)) { + if (!isUInt<20>(HiOffset) || (!isVI && !isUInt<8>(HiOffset / OffScale))) { unsigned OffsetSGPR = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass); BuildMI(*MBB, MI, DL, get(AMDGPU::S_MOV_B32), OffsetSGPR) - .addImm(HiOffset << 2); // The immediate offset is in dwords, - // but offset in register is in bytes. + .addImm(HiOffset); // The offset in register is in bytes. Hi = BuildMI(*MBB, MI, DL, get(HalfSGPROp), RegHi) .addOperand(*SBase) .addReg(OffsetSGPR); } else { Hi = BuildMI(*MBB, MI, DL, get(HalfImmOp), RegHi) .addOperand(*SBase) - .addImm(HiOffset); + .addImm(HiOffset / OffScale); } } else { // Handle the _SGPR variant @@ -1786,10 +1793,13 @@ void SIInstrInfo::moveSMRDToVALU(MachineInstr *MI, MachineRegisterInfo &MRI) con ImmOffset = 0; } else { assert(MI->getOperand(2).isImm()); - // SMRD instructions take a dword offsets and MUBUF instructions - // take a byte offset. - ImmOffset = MI->getOperand(2).getImm() << 2; + // SMRD instructions take a dword offsets on SI and byte offset on VI + // and MUBUF instructions always take a byte offset. + ImmOffset = MI->getOperand(2).getImm(); + if (RI.ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS) + ImmOffset <<= 2; RegOffset = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass); + if (isUInt<12>(ImmOffset)) { BuildMI(*MBB, MI, MI->getDebugLoc(), get(AMDGPU::S_MOV_B32), RegOffset) |

