diff options
| author | Matt Arsenault <Matthew.Arsenault@amd.com> | 2014-07-30 01:01:10 +0000 |
|---|---|---|
| committer | Matt Arsenault <Matthew.Arsenault@amd.com> | 2014-07-30 01:01:10 +0000 |
| commit | 7eb0a1014ddea55e3bbaa2bf8243480deaa2cd53 (patch) | |
| tree | 53523e67da936889888c74cd9bb5370c0b1762ea /llvm/lib | |
| parent | 2fcbe822c0be8773505afd9e4080d71f8a05953d (diff) | |
| download | bcm5719-llvm-7eb0a1014ddea55e3bbaa2bf8243480deaa2cd53.tar.gz bcm5719-llvm-7eb0a1014ddea55e3bbaa2bf8243480deaa2cd53.zip | |
R600/SI: Consider adjacent offsets in getLdStBaseRegImmOfs
We can treat ds_read2_* as a single offset if the offsets are adjacent.
No test since emission of read2 instructions for partially
aligned loads isn't implemented yet.
llvm-svn: 214269
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/R600/SIInstrInfo.cpp | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/llvm/lib/Target/R600/SIInstrInfo.cpp b/llvm/lib/Target/R600/SIInstrInfo.cpp index 045684a68d9..0249ad07208 100644 --- a/llvm/lib/Target/R600/SIInstrInfo.cpp +++ b/llvm/lib/Target/R600/SIInstrInfo.cpp @@ -37,25 +37,51 @@ bool SIInstrInfo::getLdStBaseRegImmOfs(MachineInstr *LdSt, const TargetRegisterInfo *TRI) const { unsigned Opc = LdSt->getOpcode(); if (isDS(Opc)) { - const MachineOperand *OffsetImm = getNamedOperand(*LdSt, AMDGPU::OpName::offset); + if (OffsetImm) { + // Normal, single offset LDS instruction. + const MachineOperand *AddrReg = getNamedOperand(*LdSt, + AMDGPU::OpName::addr); + + BaseReg = AddrReg->getReg(); + Offset = OffsetImm->getImm(); + return true; + } - if (!OffsetImm) { - // The 2 offset instructions use offset0 and offset1 instead. This - // function only handles simple instructions with only a single offset, so - // we ignore them. + // The 2 offset instructions use offset0 and offset1 instead. We can treat + // these as a load with a single offset if the 2 offsets are consecutive. We + // will use this for some partially aligned loads. + const MachineOperand *Offset0Imm = getNamedOperand(*LdSt, + AMDGPU::OpName::offset0); + const MachineOperand *Offset1Imm = getNamedOperand(*LdSt, + AMDGPU::OpName::offset1); + + uint8_t Offset0 = Offset0Imm->getImm(); + uint8_t Offset1 = Offset1Imm->getImm(); + assert(Offset1 > Offset0); + + if (Offset1 - Offset0 == 1) { + // Each of these offsets is in element sized units, so we need to convert + // to bytes of the individual reads. + + unsigned EltSize; + if (LdSt->mayLoad()) + EltSize = getOpRegClass(*LdSt, 0)->getSize() / 2; + else { + assert(LdSt->mayStore()); + int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0); + EltSize = getOpRegClass(*LdSt, Data0Idx)->getSize(); + } - // TODO: Handle consecutive offsets as a single load. - return false; + const MachineOperand *AddrReg = getNamedOperand(*LdSt, + AMDGPU::OpName::addr); + BaseReg = AddrReg->getReg(); + Offset = EltSize * Offset0; + return true; } - const MachineOperand *AddrReg = getNamedOperand(*LdSt, - AMDGPU::OpName::addr); - - BaseReg = AddrReg->getReg(); - Offset = OffsetImm->getImm(); - return true; + return false; } if (isMUBUF(Opc) || isMTBUF(Opc)) { |

