Index: lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp +++ lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp @@ -1176,16 +1176,6 @@ return true; } -/// -/// \param EncodedOffset This is the immediate value that will be encoded -/// directly into the instruction. On SI/CI the \p EncodedOffset -/// will be in units of dwords and on VI+ it will be units of bytes. -static bool isLegalSMRDImmOffset(const AMDGPUSubtarget *ST, - int64_t EncodedOffset) { - return ST->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS ? - isUInt<8>(EncodedOffset) : isUInt<20>(EncodedOffset); -} - bool AMDGPUDAGToDAGISel::SelectSMRDOffset(SDValue ByteOffsetNode, SDValue &Offset, bool &Imm) const { @@ -1197,10 +1187,11 @@ SDLoc SL(ByteOffsetNode); AMDGPUSubtarget::Generation Gen = Subtarget->getGeneration(); int64_t ByteOffset = C->getSExtValue(); - int64_t EncodedOffset = Gen < AMDGPUSubtarget::VOLCANIC_ISLANDS ? - ByteOffset >> 2 : ByteOffset; + int64_t EncodedOffset = + SIInstrInfo::getSMRDEncodedOffset(*Subtarget, ByteOffset); + - if (isLegalSMRDImmOffset(Subtarget, EncodedOffset)) { + if (SIInstrInfo::isLegalSMRDImmOffset(*Subtarget, ByteOffset)) { Offset = CurDAG->getTargetConstant(EncodedOffset, SL, MVT::i32); Imm = true; return true; Index: lib/Target/AMDGPU/SIISelLowering.cpp =================================================================== --- lib/Target/AMDGPU/SIISelLowering.cpp +++ lib/Target/AMDGPU/SIISelLowering.cpp @@ -681,18 +681,8 @@ bool SITargetLowering::isMemOpUniform(const SDNode *N) const { const MemSDNode *MemNode = cast(N); - const Value *Ptr = MemNode->getMemOperand()->getValue(); - - // UndefValue means this is a load of a kernel input. These are uniform. - // Sometimes LDS instructions have constant pointers. - // If Ptr is null, then that means this mem operand contains a - // PseudoSourceValue like GOT. - if (!Ptr || isa(Ptr) || isa(Ptr) || - isa(Ptr) || isa(Ptr)) - return true; - const Instruction *I = dyn_cast(Ptr); - return I && I->getMetadata("amdgpu.uniform"); + return AMDGPU::isUniformMMO(MemNode->getMemOperand()); } TargetLoweringBase::LegalizeTypeAction Index: lib/Target/AMDGPU/SIInstrInfo.h =================================================================== --- lib/Target/AMDGPU/SIInstrInfo.h +++ lib/Target/AMDGPU/SIInstrInfo.h @@ -444,6 +444,17 @@ return get(Opcode).TSFlags & SIInstrFlags::SOPK_ZEXT; } + /// \returns The encoding that will be used for \p ByteOffset in the SMRD + /// offset field. + static int64_t getSMRDEncodedOffset(const AMDGPUSubtarget &ST, + int64_t ByteOffset); + + /// \returns true if this offset is small enough to fit in the SMRD + /// offset field. \p ByteOffset should be the offset in bytes and + /// not the encoded offset. + static bool isLegalSMRDImmOffset(const AMDGPUSubtarget &ST, + int64_t ByteOffset); + /// \returns true if this is an s_store_dword* instruction. This is more /// specific than than isSMEM && mayStore. static bool isScalarStore(const MachineInstr &MI) { Index: lib/Target/AMDGPU/SIInstrInfo.cpp =================================================================== --- lib/Target/AMDGPU/SIInstrInfo.cpp +++ lib/Target/AMDGPU/SIInstrInfo.cpp @@ -2533,6 +2533,21 @@ return DstReg; } +int64_t SIInstrInfo::getSMRDEncodedOffset(const AMDGPUSubtarget &ST, + int64_t ByteOffset) { + if (ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS) + return ByteOffset >> 2; + + return ByteOffset; +} + +bool SIInstrInfo::isLegalSMRDImmOffset(const AMDGPUSubtarget &ST, + int64_t ByteOffset) { + int64_t EncodedOffset = getSMRDEncodedOffset(ST, ByteOffset); + return ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS ? + isUInt<8>(EncodedOffset) : isUInt<20>(EncodedOffset); +} + void SIInstrInfo::legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const { Index: lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h =================================================================== --- lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -24,6 +24,7 @@ class FeatureBitset; class Function; class GlobalValue; +class MachineMemOperand; class MCContext; class MCInstrDesc; class MCRegisterClass; @@ -210,6 +211,8 @@ LLVM_READNONE bool isInlinableLiteral16(int16_t Literal, bool HasInv2Pi); +bool isUniformMMO(const MachineMemOperand *MMO); + } // end namespace AMDGPU } // end namespace llvm Index: lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp =================================================================== --- lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -9,7 +9,9 @@ #include "AMDGPUBaseInfo.h" #include "AMDGPU.h" #include "SIDefines.h" +#include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" #include "llvm/MC/MCContext.h" @@ -458,5 +460,19 @@ Val == 0x3118; // 1/2pi } +bool isUniformMMO(const MachineMemOperand *MMO) { + const Value *Ptr = MMO->getValue(); + // UndefValue means this is a load of a kernel input. These are uniform. + // Sometimes LDS instructions have constant pointers. + // If Ptr is null, then that means this mem operand contains a + // PseudoSourceValue like GOT. + if (!Ptr || isa(Ptr) || isa(Ptr) || + isa(Ptr) || isa(Ptr)) + return true; + + const Instruction *I = dyn_cast(Ptr); + return I && I->getMetadata("amdgpu.uniform"); +} + } // End namespace AMDGPU } // End namespace llvm