diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -4118,20 +4118,15 @@ // For FLAT segment the offset must be positive; // MSB is ignored and forced to zero. - if (TSFlags & (SIInstrFlags::FlatGlobal | SIInstrFlags::FlatScratch)) { - unsigned OffsetSize = AMDGPU::getNumFlatOffsetBits(getSTI(), true); - if (!isIntN(OffsetSize, Op.getImm())) { - Error(getFlatOffsetLoc(Operands), - Twine("expected a ") + Twine(OffsetSize) + "-bit signed offset"); - return false; - } - } else { - unsigned OffsetSize = AMDGPU::getNumFlatOffsetBits(getSTI(), false); - if (!isUIntN(OffsetSize, Op.getImm())) { - Error(getFlatOffsetLoc(Operands), - Twine("expected a ") + Twine(OffsetSize) + "-bit unsigned offset"); - return false; - } + unsigned OffsetSize = AMDGPU::getNumFlatOffsetBits(getSTI()); + bool AllowNegative = + TSFlags & (SIInstrFlags::FlatGlobal | SIInstrFlags::FlatScratch); + if (!isIntN(OffsetSize, Op.getImm()) || (!AllowNegative && Op.getImm() < 0)) { + Error(getFlatOffsetLoc(Operands), + Twine("expected a ") + + (AllowNegative ? Twine(OffsetSize) + "-bit signed offset" + : Twine(OffsetSize - 1) + "-bit unsigned offset")); + return false; } return true; diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp --- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp @@ -7939,18 +7939,18 @@ AddrSpace == AMDGPUAS::GLOBAL_ADDRESS)) return false; - bool Signed = FlatVariant != SIInstrFlags::FLAT; + bool AllowNegative = FlatVariant != SIInstrFlags::FLAT; if (ST.hasNegativeScratchOffsetBug() && FlatVariant == SIInstrFlags::FlatScratch) - Signed = false; + AllowNegative = false; if (ST.hasNegativeUnalignedScratchOffsetBug() && FlatVariant == SIInstrFlags::FlatScratch && Offset < 0 && (Offset % 4) != 0) { return false; } - unsigned N = AMDGPU::getNumFlatOffsetBits(ST, Signed); - return Signed ? isIntN(N, Offset) : isUIntN(N, Offset); + unsigned N = AMDGPU::getNumFlatOffsetBits(ST); + return isIntN(N, Offset) && (AllowNegative || Offset >= 0); } // See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not. @@ -7959,15 +7959,15 @@ uint64_t FlatVariant) const { int64_t RemainderOffset = COffsetVal; int64_t ImmField = 0; - bool Signed = FlatVariant != SIInstrFlags::FLAT; + bool AllowNegative = FlatVariant != SIInstrFlags::FLAT; if (ST.hasNegativeScratchOffsetBug() && FlatVariant == SIInstrFlags::FlatScratch) - Signed = false; + AllowNegative = false; - const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST, Signed); - if (Signed) { + const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1; + if (AllowNegative) { // Use signed division by a power of two to truncate towards 0. - int64_t D = 1LL << (NumBits - 1); + int64_t D = 1LL << NumBits; RemainderOffset = (COffsetVal / D) * D; ImmField = COffsetVal - RemainderOffset; diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -1265,9 +1265,10 @@ /// For FLAT segment the offset must be positive; /// MSB is ignored and forced to zero. /// -/// \return The number of bits available for the offset field in flat -/// instructions. -unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST, bool Signed); +/// \return The number of bits available for the signed offset field in flat +/// instructions. Note that some forms of the instruction disallow negative +/// offsets. +unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST); /// \returns true if this offset is small enough to fit in the SMRD /// offset field. \p ByteOffset should be the offset in bytes and diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -2502,12 +2502,12 @@ : std::nullopt; } -unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST, bool Signed) { +unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST) { // Address offset is 12-bit signed for GFX10, 13-bit for GFX9 and GFX11+. if (AMDGPU::isGFX10(ST)) - return Signed ? 12 : 11; + return 12; - return Signed ? 13 : 12; + return 13; } // Given Imm, split it into the values to put into the SOffset and ImmOffset