Skip to content

Commit

Permalink
[AMDGPU][MC][GFX9+] Enabled 21-bit signed offsets for SMEM instructions
Browse files Browse the repository at this point in the history
Reviewers: arsenm, rampitec

Differential Revision: https://reviews.llvm.org/D79288
  • Loading branch information
dpreobra committed May 6, 2020
1 parent 4f7917c commit 5998bac
Show file tree
Hide file tree
Showing 15 changed files with 402 additions and 27 deletions.
57 changes: 52 additions & 5 deletions llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
Expand Up @@ -657,7 +657,7 @@ class AMDGPUOperand : public MCParsedAsmOperand {
bool isSendMsg() const;
bool isSwizzle() const;
bool isSMRDOffset8() const;
bool isSMRDOffset20() const;
bool isSMEMOffset() const;
bool isSMRDLiteralOffset() const;
bool isDPP8() const;
bool isDPPCtrl() const;
Expand Down Expand Up @@ -1326,9 +1326,11 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
void errorExpTgt();
OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
SMLoc getFlatOffsetLoc(const OperandVector &Operands) const;
SMLoc getSMEMOffsetLoc(const OperandVector &Operands) const;

bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc, const OperandVector &Operands);
bool validateFlatOffset(const MCInst &Inst, const OperandVector &Operands);
bool validateSMEMOffset(const MCInst &Inst, const OperandVector &Operands);
bool validateSOPLiteral(const MCInst &Inst) const;
bool validateConstantBusLimitations(const MCInst &Inst);
bool validateEarlyClobberLimitations(const MCInst &Inst);
Expand Down Expand Up @@ -1405,7 +1407,7 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
AMDGPUOperand::Ptr defaultSLC() const;

AMDGPUOperand::Ptr defaultSMRDOffset8() const;
AMDGPUOperand::Ptr defaultSMRDOffset20() const;
AMDGPUOperand::Ptr defaultSMEMOffset() const;
AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
AMDGPUOperand::Ptr defaultFlatOffset() const;

Expand Down Expand Up @@ -3395,6 +3397,46 @@ bool AMDGPUAsmParser::validateFlatOffset(const MCInst &Inst,
return true;
}

SMLoc AMDGPUAsmParser::getSMEMOffsetLoc(const OperandVector &Operands) const {
for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
if (Op.isSMEMOffset())
return Op.getStartLoc();
}
return getLoc();
}

bool AMDGPUAsmParser::validateSMEMOffset(const MCInst &Inst,
const OperandVector &Operands) {
if (isCI() || isSI())
return true;

uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
if ((TSFlags & SIInstrFlags::SMRD) == 0)
return true;

auto Opcode = Inst.getOpcode();
auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset);
if (OpNum == -1)
return true;

const auto &Op = Inst.getOperand(OpNum);
if (!Op.isImm())
return true;

uint64_t Offset = Op.getImm();
bool IsBuffer = AMDGPU::getSMEMIsBuffer(Opcode);
if (AMDGPU::isLegalSMRDEncodedUnsignedOffset(getSTI(), Offset) ||
AMDGPU::isLegalSMRDEncodedSignedOffset(getSTI(), Offset, IsBuffer))
return true;

Error(getSMEMOffsetLoc(Operands),
(isVI() || IsBuffer) ? "expected a 20-bit unsigned offset" :
"expected a 21-bit signed offset");

return false;
}

bool AMDGPUAsmParser::validateSOPLiteral(const MCInst &Inst) const {
unsigned Opcode = Inst.getOpcode();
const MCInstrDesc &Desc = MII.get(Opcode);
Expand Down Expand Up @@ -3572,6 +3614,9 @@ bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst,
if (!validateFlatOffset(Inst, Operands)) {
return false;
}
if (!validateSMEMOffset(Inst, Operands)) {
return false;
}

return true;
}
Expand Down Expand Up @@ -6071,8 +6116,8 @@ bool AMDGPUOperand::isSMRDOffset8() const {
return isImm() && isUInt<8>(getImm());
}

bool AMDGPUOperand::isSMRDOffset20() const {
return isImm() && isUInt<20>(getImm());
bool AMDGPUOperand::isSMEMOffset() const {
return isImm(); // Offset range is checked later by validator.
}

bool AMDGPUOperand::isSMRDLiteralOffset() const {
Expand All @@ -6085,7 +6130,7 @@ AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const {
return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
}

AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const {
AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMEMOffset() const {
return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
}

Expand Down Expand Up @@ -7097,6 +7142,8 @@ unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
case MCK_AttrChan:
return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
case MCK_ImmSMEMOffset:
return Operand.isSMEMOffset() ? Match_Success : Match_InvalidOperand;
case MCK_SReg_64:
case MCK_SReg_64_XEXEC:
// Null is defined as a 32-bit register but
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
Expand Up @@ -100,6 +100,18 @@ static DecodeStatus decodeSoppBrTarget(MCInst &Inst, unsigned Imm,
return addOperand(Inst, MCOperand::createImm(Imm));
}

static DecodeStatus decodeSMEMOffset(MCInst &Inst, unsigned Imm,
uint64_t Addr, const void *Decoder) {
auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
int64_t Offset;
if (DAsm->isVI()) { // VI supports 20-bit unsigned offsets.
Offset = Imm & 0xFFFFF;
} else { // GFX9+ supports 21-bit signed offsets.
Offset = SignExtend64<21>(Imm);
}
return addOperand(Inst, MCOperand::createImm(Offset));
}

static DecodeStatus decodeBoolReg(MCInst &Inst, unsigned Val,
uint64_t Addr, const void *Decoder) {
auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
Expand Up @@ -180,10 +180,10 @@ void AMDGPUInstPrinter::printSMRDOffset8(const MCInst *MI, unsigned OpNo,
printU32ImmOperand(MI, OpNo, STI, O);
}

void AMDGPUInstPrinter::printSMRDOffset20(const MCInst *MI, unsigned OpNo,
void AMDGPUInstPrinter::printSMEMOffset(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI,
raw_ostream &O) {
printU32ImmOperand(MI, OpNo, STI, O);
O << formatHex(MI->getOperand(OpNo).getImm());
}

void AMDGPUInstPrinter::printSMRDLiteralOffset(const MCInst *MI, unsigned OpNo,
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.h
Expand Up @@ -61,7 +61,7 @@ class AMDGPUInstPrinter : public MCInstPrinter {
raw_ostream &O);
void printSMRDOffset8(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
void printSMRDOffset20(const MCInst *MI, unsigned OpNo,
void printSMEMOffset(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
void printSMRDLiteralOffset(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.h
Expand Up @@ -51,6 +51,12 @@ class AMDGPUMCCodeEmitter : public MCCodeEmitter {
return 0;
}

virtual unsigned getSMEMOffsetEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
return 0;
}

virtual unsigned getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/Target/AMDGPU/MCTargetDesc/SIMCCodeEmitter.cpp
Expand Up @@ -70,6 +70,10 @@ class SIMCCodeEmitter : public AMDGPUMCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const override;

unsigned getSMEMOffsetEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const override;

unsigned getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const override;
Expand Down Expand Up @@ -358,6 +362,15 @@ unsigned SIMCCodeEmitter::getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
return getMachineOpValue(MI, MO, Fixups, STI);
}

unsigned SIMCCodeEmitter::getSMEMOffsetEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
auto Offset = MI.getOperand(OpNo).getImm();
// VI only supports 20-bit unsigned offsets.
assert(!AMDGPU::isVI(STI) || isUInt<20>(Offset));
return Offset;
}

unsigned
SIMCCodeEmitter::getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
Expand Down

0 comments on commit 5998bac

Please sign in to comment.