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 @@ -1542,6 +1542,7 @@ int64_t Id; bool IsSymbolic = false; bool IsDefined = false; + StringRef Name; OperandInfoTy(int64_t Id_) : Id(Id_) {} }; @@ -6245,6 +6246,7 @@ if (isToken(AsmToken::Identifier) && (HwReg.Id = getHwregId(getTokenStr(), getSTI())) >= 0) { HwReg.IsSymbolic = true; + HwReg.Name = getTokenStr(); lex(); // skip register name } else if (!parseExpr(HwReg.Id, "a register name")) { return false; @@ -6276,7 +6278,8 @@ using namespace llvm::AMDGPU::Hwreg; - if (HwReg.IsSymbolic && !isValidHwreg(HwReg.Id, getSTI())) { + if (HwReg.IsSymbolic && + !isValidHwreg(HwReg.Id, getSTI(), HwReg.Name)) { Error(HwReg.Loc, "specified hardware register is not supported on this GPU"); return false; diff --git a/llvm/lib/Target/AMDGPU/SIDefines.h b/llvm/lib/Target/AMDGPU/SIDefines.h --- a/llvm/lib/Target/AMDGPU/SIDefines.h +++ b/llvm/lib/Target/AMDGPU/SIDefines.h @@ -378,6 +378,13 @@ ID_TBA_HI = 17, ID_TMA_LO = 18, ID_TMA_HI = 19, + ID_XCC_ID = 20, + ID_SYMBOLIC_FIRST_GFX940_ = ID_XCC_ID, + ID_SQ_PERF_SNAPSHOT_DATA = 21, + ID_SQ_PERF_SNAPSHOT_DATA1 = 22, + ID_SQ_PERF_SNAPSHOT_PC_LO = 23, + ID_SQ_PERF_SNAPSHOT_PC_HI = 24, + ID_SYMBOLIC_LAST_GFX940_ = ID_SQ_PERF_SNAPSHOT_PC_HI + 1, ID_FLAT_SCR_LO = 20, ID_SYMBOLIC_FIRST_GFX10_ = ID_FLAT_SCR_LO, ID_FLAT_SCR_HI = 21, diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h @@ -28,6 +28,7 @@ namespace Hwreg { // Symbolic names for the hwreg(...) syntax. extern const char* const IdSymbolic[]; +extern const char* const IdSymbolicGFX940Specific[]; } // namespace Hwreg diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp @@ -88,6 +88,16 @@ "HW_REG_SHADER_CYCLES" }; +// This is gfx940 specific portion from ID_SYMBOLIC_FIRST_GFX940_ to +// ID_SYMBOLIC_LAST_GFX940_ +const char* const IdSymbolicGFX940Specific[] = { + "HW_REG_XCC_ID", + "HW_REG_SQ_PERF_SNAPSHOT_DATA", + "HW_REG_SQ_PERF_SNAPSHOT_DATA1", + "HW_REG_SQ_PERF_SNAPSHOT_PC_LO", + "HW_REG_SQ_PERF_SNAPSHOT_PC_HI" +}; + } // namespace Hwreg namespace MTBUFFormat { 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 @@ -612,8 +612,8 @@ LLVM_READONLY int64_t getHwregId(const StringRef Name, const MCSubtargetInfo &STI); -LLVM_READNONE -bool isValidHwreg(int64_t Id, const MCSubtargetInfo &STI); +LLVM_READONLY +bool isValidHwreg(int64_t Id, const MCSubtargetInfo &STI, StringRef Name); LLVM_READNONE bool isValidHwreg(int64_t Id); 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 @@ -1044,12 +1044,24 @@ namespace Hwreg { +static const char* getHwregName(int64_t Id, const MCSubtargetInfo &STI) { + if (isGFX940(STI) && Id >= ID_SYMBOLIC_FIRST_GFX940_ && + Id < ID_SYMBOLIC_LAST_GFX940_) + return IdSymbolicGFX940Specific[Id - ID_SYMBOLIC_FIRST_GFX940_]; + return (Id < ID_SYMBOLIC_LAST_) ? IdSymbolic[Id] : nullptr; +} + int64_t getHwregId(const StringRef Name, const MCSubtargetInfo &STI) { if (isGFX10(STI) && Name == "HW_REG_HW_ID") // An alias return ID_HW_ID1; for (int Id = ID_SYMBOLIC_FIRST_; Id < ID_SYMBOLIC_LAST_; ++Id) { if (IdSymbolic[Id] && Name == IdSymbolic[Id]) return Id; + // These are all defined, however may be invalid for subtarget and need + // further validation. + if (Id >= ID_SYMBOLIC_FIRST_GFX940_ && Id < ID_SYMBOLIC_LAST_GFX940_ && + Name == IdSymbolicGFX940Specific[Id - ID_SYMBOLIC_FIRST_GFX940_]) + return Id; } return ID_UNKNOWN_; } @@ -1057,6 +1069,8 @@ static unsigned getLastSymbolicHwreg(const MCSubtargetInfo &STI) { if (isSI(STI) || isCI(STI) || isVI(STI)) return ID_SYMBOLIC_FIRST_GFX9_; + else if (isGFX940(STI)) + return ID_SYMBOLIC_LAST_GFX940_; else if (isGFX9(STI)) return ID_SYMBOLIC_FIRST_GFX10_; else if (isGFX10(STI) && !isGFX10_BEncoding(STI)) @@ -1065,19 +1079,34 @@ return ID_SYMBOLIC_LAST_; } -bool isValidHwreg(int64_t Id, const MCSubtargetInfo &STI) { - switch (Id) { - case ID_HW_ID: - return isSI(STI) || isCI(STI) || isVI(STI) || isGFX9(STI); - case ID_HW_ID1: - case ID_HW_ID2: - return isGFX10Plus(STI); - case ID_XNACK_MASK: - return isGFX10(STI) && !AMDGPU::isGFX10_BEncoding(STI); - default: - return ID_SYMBOLIC_FIRST_ <= Id && Id < getLastSymbolicHwreg(STI) && - IdSymbolic[Id]; +bool isValidHwreg(int64_t Id, const MCSubtargetInfo &STI, StringRef Name) { + if (isGFX10(STI) && Name == "HW_REG_HW_ID") // An alias + return true; + + const char *HWRegName = getHwregName(Id, STI); + if (!HWRegName || !Name.startswith(HWRegName)) + return false; + + if (isGFX10Plus(STI)) { + switch (Id) { + case ID_HW_ID1: + case ID_HW_ID2: + return true; + case ID_XNACK_MASK: + return !AMDGPU::isGFX10_BEncoding(STI); + default: + break; + } } + + if (ID_SYMBOLIC_FIRST_ > Id || Id >= getLastSymbolicHwreg(STI)) + return false; + + if (isGFX940(STI) && Id >= ID_SYMBOLIC_FIRST_GFX10_ && + Id < ID_SYMBOLIC_FIRST_GFX940_) + return false; + + return true; } bool isValidHwreg(int64_t Id) { @@ -1099,7 +1128,8 @@ } StringRef getHwreg(unsigned Id, const MCSubtargetInfo &STI) { - return isValidHwreg(Id, STI) ? IdSymbolic[Id] : ""; + const char *HWRegName = getHwregName(Id, STI); + return (HWRegName && isValidHwreg(Id, STI, HWRegName)) ? HWRegName : ""; } void decodeHwreg(unsigned Val, unsigned &Id, unsigned &Offset, unsigned &Width) { diff --git a/llvm/test/MC/AMDGPU/gfx940_asm_features.s b/llvm/test/MC/AMDGPU/gfx940_asm_features.s --- a/llvm/test/MC/AMDGPU/gfx940_asm_features.s +++ b/llvm/test/MC/AMDGPU/gfx940_asm_features.s @@ -197,6 +197,47 @@ // GFX940: scratch_load_lds_sshort v2, off ; encoding: [0x00,0x60,0xa4,0xdc,0x02,0x00,0x7f,0x00] scratch_load_lds_sshort v2, off +// NOT-GFX940: error: specified hardware register is not supported on this GPU +// GFX940: s_getreg_b32 s1, hwreg(HW_REG_XCC_ID) ; encoding: [0x14,0xf8,0x81,0xb8] +s_getreg_b32 s1, hwreg(HW_REG_XCC_ID) + +// NOT-GFX940: error: specified hardware register is not supported on this GPU +// GFX940: s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_DATA) ; encoding: [0x15,0xf8,0x81,0xb8] +s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_DATA) + +// NOT-GFX940: error: specified hardware register is not supported on this GPU +// GFX940: s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_DATA1) ; encoding: [0x16,0xf8,0x81,0xb8] +s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_DATA1) + +// NOT-GFX940: error: specified hardware register is not supported on this GPU +// GFX940: s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_PC_LO) ; encoding: [0x17,0xf8,0x81,0xb8] +s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_PC_LO) + +// NOT-GFX940: error: specified hardware register is not supported on this GPU +// GFX940: s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_PC_HI) ; encoding: [0x18,0xf8,0x81,0xb8] +s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_PC_HI) + +// GFX940: s_getreg_b32 s1, hwreg(HW_REG_TMA_HI) ; encoding: [0x13,0xf8,0x81,0xb8] +s_getreg_b32 s1, hwreg(19) + +// GFX940: s_getreg_b32 s1, hwreg(HW_REG_XCC_ID) ; encoding: [0x14,0xf8,0x81,0xb8] +s_getreg_b32 s1, hwreg(20) + +// GFX940: s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_DATA) ; encoding: [0x15,0xf8,0x81,0xb8] +s_getreg_b32 s1, hwreg(21) + +// GFX940: s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_DATA1) ; encoding: [0x16,0xf8,0x81,0xb8] +s_getreg_b32 s1, hwreg(22) + +// GFX940: s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_PC_LO) ; encoding: [0x17,0xf8,0x81,0xb8] +s_getreg_b32 s1, hwreg(23) + +// GFX940: s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_PC_HI) ; encoding: [0x18,0xf8,0x81,0xb8] +s_getreg_b32 s1, hwreg(24) + +// GFX940: s_getreg_b32 s1, hwreg(25) ; encoding: [0x19,0xf8,0x81,0xb8] +s_getreg_b32 s1, hwreg(25) + // NOT-GFX940: error: instruction not supported on this GPU // GFX940: v_mov_b64_e32 v[2:3], v[4:5] ; encoding: [0x04,0x71,0x04,0x7e] v_mov_b64 v[2:3], v[4:5] diff --git a/llvm/test/MC/AMDGPU/gfx940_err.s b/llvm/test/MC/AMDGPU/gfx940_err.s --- a/llvm/test/MC/AMDGPU/gfx940_err.s +++ b/llvm/test/MC/AMDGPU/gfx940_err.s @@ -57,3 +57,21 @@ buffer_wbl2 scc // GFX940: error: invalid operand for instruction + +s_getreg_b32 s1, hwreg(HW_REG_FLAT_SCR_LO) +// GFX940: error: specified hardware register is not supported on this GPU + +s_getreg_b32 s1, hwreg(HW_REG_FLAT_SCR_HI) +// GFX940: error: specified hardware register is not supported on this GPU + +s_getreg_b32 s1, hwreg(HW_REG_XNACK_MASK) +// GFX940: error: specified hardware register is not supported on this GPU + +s_getreg_b32 s1, hwreg(HW_REG_HW_ID1) +// GFX940: error: specified hardware register is not supported on this GPU + +s_getreg_b32 s1, hwreg(HW_REG_HW_ID2) +// GFX940: error: specified hardware register is not supported on this GPU + +s_getreg_b32 s1, hwreg(HW_REG_POPS_PACKER) +// GFX940: error: specified hardware register is not supported on this GPU diff --git a/llvm/test/MC/Disassembler/AMDGPU/gfx940_dasm_features.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx940_dasm_features.txt --- a/llvm/test/MC/Disassembler/AMDGPU/gfx940_dasm_features.txt +++ b/llvm/test/MC/Disassembler/AMDGPU/gfx940_dasm_features.txt @@ -141,6 +141,21 @@ # GFX940: scratch_load_lds_sshort v2, off ; encoding: [0x00,0x60,0xa4,0xdc,0x02,0x00,0x7f,0x00] 0x00,0x60,0xa4,0xdc,0x02,0x00,0x7f,0x00 +# GFX940: s_getreg_b32 s1, hwreg(HW_REG_XCC_ID) ; encoding: [0x14,0xf8,0x81,0xb8] +0x14,0xf8,0x81,0xb8 + +# GFX940: s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_DATA) ; encoding: [0x15,0xf8,0x81,0xb8] +0x15,0xf8,0x81,0xb8 + +# GFX940: s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_DATA1) ; encoding: [0x16,0xf8,0x81,0xb8] +0x16,0xf8,0x81,0xb8 + +# GFX940: s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_PC_LO) ; encoding: [0x17,0xf8,0x81,0xb8] +0x17,0xf8,0x81,0xb8 + +# GFX940: s_getreg_b32 s1, hwreg(HW_REG_SQ_PERF_SNAPSHOT_PC_HI) ; encoding: [0x18,0xf8,0x81,0xb8] +0x18,0xf8,0x81,0xb8 + # GFX940: v_mov_b64_e32 v[2:3], v[4:5] ; encoding: [0x04,0x71,0x04,0x7e] 0x04,0x71,0x04,0x7e