Skip to content

Commit

Permalink
[AMDGPU][MC][GFX10] Added syntactic sugar for s_waitcnt_depctr operand
Browse files Browse the repository at this point in the history
Added the following helpers:

    depctr_hold_cnt(...)
    depctr_sa_sdst(...)
    depctr_va_vdst(...)
    depctr_va_sdst(...)
    depctr_va_ssrc(...)
    depctr_va_vcc(...)
    depctr_vm_vsrc(...)

Differential Revision: https://reviews.llvm.org/D123022
  • Loading branch information
dpreobra committed Apr 7, 2022
1 parent cde66d5 commit 1f6aa90
Show file tree
Hide file tree
Showing 15 changed files with 808 additions and 10 deletions.
91 changes: 91 additions & 0 deletions llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
Expand Up @@ -818,6 +818,7 @@ class AMDGPUOperand : public MCParsedAsmOperand {
}

bool isSWaitCnt() const;
bool isDepCtr() const;
bool isHwreg() const;
bool isSendMsg() const;
bool isSwizzle() const;
Expand Down Expand Up @@ -1543,6 +1544,11 @@ class AMDGPUAsmParser : public MCTargetAsmParser {

bool parseCnt(int64_t &IntVal);
OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);

bool parseDepCtr(int64_t &IntVal, unsigned &Mask);
void depCtrError(SMLoc Loc, int ErrorId, StringRef DepCtrName);
OperandMatchResultTy parseDepCtrOps(OperandVector &Operands);

OperandMatchResultTy parseHwreg(OperandVector &Operands);

private:
Expand Down Expand Up @@ -6333,6 +6339,91 @@ AMDGPUOperand::isSWaitCnt() const {
return isImm();
}

//===----------------------------------------------------------------------===//
// DepCtr
//===----------------------------------------------------------------------===//

void AMDGPUAsmParser::depCtrError(SMLoc Loc, int ErrorId,
StringRef DepCtrName) {
switch (ErrorId) {
case OPR_ID_UNKNOWN:
Error(Loc, Twine("invalid counter name ", DepCtrName));
return;
case OPR_ID_UNSUPPORTED:
Error(Loc, Twine(DepCtrName, " is not supported on this GPU"));
return;
case OPR_ID_DUPLICATE:
Error(Loc, Twine("duplicate counter name ", DepCtrName));
return;
case OPR_VAL_INVALID:
Error(Loc, Twine("invalid value for ", DepCtrName));
return;
default:
assert(false);
}
}

bool AMDGPUAsmParser::parseDepCtr(int64_t &DepCtr, unsigned &UsedOprMask) {

using namespace llvm::AMDGPU::DepCtr;

SMLoc DepCtrLoc = getLoc();
StringRef DepCtrName = getTokenStr();

if (!skipToken(AsmToken::Identifier, "expected a counter name") ||
!skipToken(AsmToken::LParen, "expected a left parenthesis"))
return false;

int64_t ExprVal;
if (!parseExpr(ExprVal))
return false;

unsigned PrevOprMask = UsedOprMask;
int CntVal = encodeDepCtr(DepCtrName, ExprVal, UsedOprMask, getSTI());

if (CntVal < 0) {
depCtrError(DepCtrLoc, CntVal, DepCtrName);
return false;
}

if (!skipToken(AsmToken::RParen, "expected a closing parenthesis"))
return false;

if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) {
if (isToken(AsmToken::EndOfStatement)) {
Error(getLoc(), "expected a counter name");
return false;
}
}

unsigned CntValMask = PrevOprMask ^ UsedOprMask;
DepCtr = (DepCtr & ~CntValMask) | CntVal;
return true;
}

OperandMatchResultTy AMDGPUAsmParser::parseDepCtrOps(OperandVector &Operands) {
using namespace llvm::AMDGPU::DepCtr;

int64_t DepCtr = getDefaultDepCtrEncoding(getSTI());
SMLoc Loc = getLoc();

if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
unsigned UsedOprMask = 0;
while (!isToken(AsmToken::EndOfStatement)) {
if (!parseDepCtr(DepCtr, UsedOprMask))
return MatchOperand_ParseFail;
}
} else {
if (!parseExpr(DepCtr))
return MatchOperand_ParseFail;
}

Operands.push_back(AMDGPUOperand::CreateImm(this, DepCtr, Loc));
return MatchOperand_Success;
}

bool AMDGPUOperand::isDepCtr() const { return isS16Imm(); }

//===----------------------------------------------------------------------===//
// hwreg
//===----------------------------------------------------------------------===//
Expand Down
27 changes: 27 additions & 0 deletions llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
Expand Up @@ -1438,6 +1438,33 @@ void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
}
}

void AMDGPUInstPrinter::printDepCtr(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI,
raw_ostream &O) {
using namespace llvm::AMDGPU::DepCtr;

uint64_t Imm16 = MI->getOperand(OpNo).getImm() & 0xffff;

bool HasNonDefaultVal = false;
if (isSymbolicDepCtrEncoding(Imm16, HasNonDefaultVal, STI)) {
int Id = 0;
StringRef Name;
unsigned Val;
bool IsDefault;
bool NeedSpace = false;
while (decodeDepCtr(Imm16, Id, Name, Val, IsDefault, STI)) {
if (!IsDefault || !HasNonDefaultVal) {
if (NeedSpace)
O << ' ';
O << Name << '(' << Val << ')';
NeedSpace = true;
}
}
} else {
O << formatHex(Imm16);
}
}

void AMDGPUInstPrinter::printHwreg(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O) {
unsigned Id;
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.h
Expand Up @@ -234,6 +234,8 @@ class AMDGPUInstPrinter : public MCInstPrinter {
raw_ostream &O);
void printWaitFlag(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
void printDepCtr(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
raw_ostream &O);
void printHwreg(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
raw_ostream &O);
void printEndpgm(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Target/AMDGPU/SIInstrInfo.td
Expand Up @@ -1016,6 +1016,12 @@ def SWaitMatchClass : AsmOperandClass {
let ParserMethod = "parseSWaitCntOps";
}

def DepCtrMatchClass : AsmOperandClass {
let Name = "DepCtr";
let RenderMethod = "addImmOperands";
let ParserMethod = "parseDepCtrOps";
}

def VReg32OrOffClass : AsmOperandClass {
let Name = "VReg32OrOff";
let ParserMethod = "parseVReg32OrOff";
Expand All @@ -1041,6 +1047,11 @@ def WAIT_FLAG : Operand <i32> {
let ParserMatchClass = SWaitMatchClass;
let PrintMethod = "printWaitFlag";
}

def DepCtrImm : Operand <i32> {
let ParserMatchClass = DepCtrMatchClass;
let PrintMethod = "printDepCtr";
}
} // End OperandType = "OPERAND_IMMEDIATE"

include "SIInstrFormats.td"
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AMDGPU/SOPInstructions.td
Expand Up @@ -1343,7 +1343,7 @@ let SubtargetPredicate = isGFX10Plus in {
let fixed_imm = 1;
}
def S_WAITCNT_DEPCTR :
SOPP_Pseudo <"s_waitcnt_depctr" , (ins s16imm:$simm16), "$simm16">;
SOPP_Pseudo <"s_waitcnt_depctr" , (ins DepCtrImm:$simm16), "$simm16">;

let hasSideEffects = 0, Uses = [MODE], Defs = [MODE] in {
def S_ROUND_MODE :
Expand Down
21 changes: 21 additions & 0 deletions llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp
Expand Up @@ -11,6 +11,27 @@

namespace llvm {
namespace AMDGPU {

namespace DepCtr {

// NOLINTBEGIN
const CustomOperandVal DepCtrInfo[] = {
// Name max dflt offset width constraint
{{"depctr_hold_cnt"}, 1, 1, 7, 1, isGFX10_BEncoding},
{{"depctr_sa_sdst"}, 1, 1, 0, 1},
{{"depctr_va_vdst"}, 15, 15, 12, 4},
{{"depctr_va_sdst"}, 7, 7, 9, 3},
{{"depctr_va_ssrc"}, 1, 1, 8, 1},
{{"depctr_va_vcc"}, 1, 1, 1, 1},
{{"depctr_vm_vsrc"}, 7, 7, 2, 3},
};
// NOLINTEND

const int DEP_CTR_SIZE =
static_cast<int>(sizeof(DepCtrInfo) / sizeof(CustomOperandVal));

} // namespace DepCtr

namespace SendMsg {

// Disable lint checking for this block since it makes the table unreadable.
Expand Down
31 changes: 31 additions & 0 deletions llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h
Expand Up @@ -22,13 +22,44 @@ namespace AMDGPU {

const int OPR_ID_UNKNOWN = -1;
const int OPR_ID_UNSUPPORTED = -2;
const int OPR_ID_DUPLICATE = -3;
const int OPR_VAL_INVALID = -4;

template <class T> struct CustomOperand {
StringLiteral Name;
int Encoding = 0;
bool (*Cond)(T Context) = nullptr;
};

struct CustomOperandVal {
StringLiteral Name;
unsigned Max;
unsigned Default;
unsigned Shift;
unsigned Width;
bool (*Cond)(const MCSubtargetInfo &STI) = nullptr;
unsigned Mask = (1 << Width) - 1;

unsigned decode(unsigned Code) const { return (Code >> Shift) & Mask; }

unsigned encode(unsigned Val) const { return (Val & Mask) << Shift; }

unsigned getMask() const { return Mask << Shift; }

bool isValid(unsigned Val) const { return Val <= Max; }

bool isSupported(const MCSubtargetInfo &STI) const {
return !Cond || Cond(STI);
}
};

namespace DepCtr {

extern const CustomOperandVal DepCtrInfo[];
extern const int DEP_CTR_SIZE;

} // namespace DepCtr

namespace SendMsg { // Symbolic names for the sendmsg(...) syntax.

extern const CustomOperand<const MCSubtargetInfo &> Msg[];
Expand Down
114 changes: 114 additions & 0 deletions llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
Expand Up @@ -1091,6 +1091,120 @@ static int getOprIdx(int Id, const CustomOperand<T> OpInfo[], int OpInfoSize,
return getOprIdx<T>(Test, OpInfo, OpInfoSize, Context);
}

//===----------------------------------------------------------------------===//
// Custom Operand Values
//===----------------------------------------------------------------------===//

static unsigned getDefaultCustomOperandEncoding(const CustomOperandVal *Opr,
int Size,
const MCSubtargetInfo &STI) {
unsigned Enc = 0;
for (int Idx = 0; Idx < Size; ++Idx) {
const auto &Op = Opr[Idx];
if (Op.isSupported(STI))
Enc |= Op.encode(Op.Default);
}
return Enc;
}

static bool isSymbolicCustomOperandEncoding(const CustomOperandVal *Opr,
int Size, unsigned Code,
bool &HasNonDefaultVal,
const MCSubtargetInfo &STI) {
unsigned UsedOprMask = 0;
HasNonDefaultVal = false;
for (int Idx = 0; Idx < Size; ++Idx) {
const auto &Op = Opr[Idx];
if (!Op.isSupported(STI))
continue;
UsedOprMask |= Op.getMask();
unsigned Val = Op.decode(Code);
if (!Op.isValid(Val))
return false;
HasNonDefaultVal |= (Val != Op.Default);
}
return (Code & ~UsedOprMask) == 0;
}

static bool decodeCustomOperand(const CustomOperandVal *Opr, int Size,
unsigned Code, int &Idx, StringRef &Name,
unsigned &Val, bool &IsDefault,
const MCSubtargetInfo &STI) {
while (Idx < Size) {
const auto &Op = Opr[Idx++];
if (Op.isSupported(STI)) {
Name = Op.Name;
Val = Op.decode(Code);
IsDefault = (Val == Op.Default);
return true;
}
}

return false;
}

static int encodeCustomOperandVal(const CustomOperandVal &Op,
int64_t InputVal) {
if (InputVal < 0 || InputVal > Op.Max)
return OPR_VAL_INVALID;
return Op.encode(InputVal);
}

static int encodeCustomOperand(const CustomOperandVal *Opr, int Size,
const StringRef Name, int64_t InputVal,
unsigned &UsedOprMask,
const MCSubtargetInfo &STI) {
int InvalidId = OPR_ID_UNKNOWN;
for (int Idx = 0; Idx < Size; ++Idx) {
const auto &Op = Opr[Idx];
if (Op.Name == Name) {
if (!Op.isSupported(STI)) {
InvalidId = OPR_ID_UNSUPPORTED;
continue;
}
auto OprMask = Op.getMask();
if (OprMask & UsedOprMask)
return OPR_ID_DUPLICATE;
UsedOprMask |= OprMask;
return encodeCustomOperandVal(Op, InputVal);
}
}
return InvalidId;
}

//===----------------------------------------------------------------------===//
// DepCtr
//===----------------------------------------------------------------------===//

namespace DepCtr {

int getDefaultDepCtrEncoding(const MCSubtargetInfo &STI) {
static int Default = -1;
if (Default == -1)
Default = getDefaultCustomOperandEncoding(DepCtrInfo, DEP_CTR_SIZE, STI);
return Default;
}

bool isSymbolicDepCtrEncoding(unsigned Code, bool &HasNonDefaultVal,
const MCSubtargetInfo &STI) {
return isSymbolicCustomOperandEncoding(DepCtrInfo, DEP_CTR_SIZE, Code,
HasNonDefaultVal, STI);
}

bool decodeDepCtr(unsigned Code, int &Id, StringRef &Name, unsigned &Val,
bool &IsDefault, const MCSubtargetInfo &STI) {
return decodeCustomOperand(DepCtrInfo, DEP_CTR_SIZE, Code, Id, Name, Val,
IsDefault, STI);
}

int encodeDepCtr(const StringRef Name, int64_t Val, unsigned &UsedOprMask,
const MCSubtargetInfo &STI) {
return encodeCustomOperand(DepCtrInfo, DEP_CTR_SIZE, Name, Val, UsedOprMask,
STI);
}

} // namespace DepCtr

//===----------------------------------------------------------------------===//
// hwreg
//===----------------------------------------------------------------------===//
Expand Down

0 comments on commit 1f6aa90

Please sign in to comment.