[PATCH] R600/SI: Start implementing an assembler
Matt Arsenault
Matthew.Arsenault at amd.com
Wed Nov 12 12:02:33 PST 2014
On 11/12/2014 11:18 AM, Tom Stellard wrote:
> On Thu, Nov 06, 2014 at 11:28:48AM -0800, Matt Arsenault wrote:
>> >
>>> > >On Nov 5, 2014, at 8:05 PM, Tom Stellard<thomas.stellard at amd.com> wrote:
>>> > >
>>> > >This was done using PowerPCAsmParser as a guide. So far it is very
>>> > >simple and only supports a few sopp instructions.
>>> > >---
>>> > >lib/Target/R600/AMDGPU.td | 7 +
>>> > >lib/Target/R600/AMDGPUInstructions.td | 2 +
>>> > >lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp | 224 ++++++++++++++++++++++++++
>>> > >lib/Target/R600/AsmParser/CMakeLists.txt | 3 +
>>> > >lib/Target/R600/AsmParser/LLVMBuild.txt | 23 +++
>>> > >lib/Target/R600/AsmParser/Makefile | 15 ++
>>> > >lib/Target/R600/CMakeLists.txt | 2 +
>>> > >lib/Target/R600/LLVMBuild.txt | 5 +-
>>> > >lib/Target/R600/Makefile | 4 +-
>>> > >lib/Target/R600/R600InstrFormats.td | 3 +
>>> > >lib/Target/R600/R600Instructions.td | 1 +
>>> > >lib/Target/R600/SIInstrFormats.td | 3 +-
>>> > >lib/Target/R600/SIInstructions.td | 40 ++---
>>> > >test/MC/R600/lit.local.cfg | 2 +
>>> > >test/MC/R600/sopp.s | 23 +++
>>> > >15 files changed, 332 insertions(+), 25 deletions(-)
>>> > >create mode 100644 lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
>>> > >create mode 100644 lib/Target/R600/AsmParser/CMakeLists.txt
>>> > >create mode 100644 lib/Target/R600/AsmParser/LLVMBuild.txt
>>> > >create mode 100644 lib/Target/R600/AsmParser/Makefile
>>> > >create mode 100644 test/MC/R600/lit.local.cfg
>>> > >create mode 100644 test/MC/R600/sopp.s
>>> > >
>>> > >diff --git a/lib/Target/R600/AMDGPU.td b/lib/Target/R600/AMDGPU.td
>>> > >index f5930f5..4cf1243 100644
>>> > >--- a/lib/Target/R600/AMDGPU.td
>>> > >+++ b/lib/Target/R600/AMDGPU.td
>>> > >@@ -153,9 +153,16 @@ def AMDGPUInstrInfo : InstrInfo {
>>> > > let guessInstructionProperties = 1;
>>> > >}
>>> > >
>>> > >+def AMDGPUAsmParser : AsmParser {
>>> > >+ // Some of the R600 registers have the same name, so this crashes.
>>> > >+ // For example T0_XYZW and T0_XY both have the asm name T0.
>>> > >+ let ShouldEmitMatchRegisterName = 0;
>>> > >+}
>>> > >+
>>> > >def AMDGPU : Target {
>>> > > // Pull in Instruction Info:
>>> > > let InstructionSet = AMDGPUInstrInfo;
>>> > >+ let AssemblyParsers = [AMDGPUAsmParser];
>>> > >}
>>> > >
>>> > >// Dummy Instruction itineraries for pseudo instructions
>>> > >diff --git a/lib/Target/R600/AMDGPUInstructions.td b/lib/Target/R600/AMDGPUInstructions.td
>>> > >index ba5630e..c215865 100644
>>> > >--- a/lib/Target/R600/AMDGPUInstructions.td
>>> > >+++ b/lib/Target/R600/AMDGPUInstructions.td
>>> > >@@ -23,6 +23,8 @@ class AMDGPUInst <dag outs, dag ins, string asm, list<dag> pattern> : Instructio
>>> > > let Pattern = pattern;
>>> > > let Itinerary = NullALU;
>>> > >
>>> > >+ let isCodeGenOnly = 1;
>>> > >+
>>> > > let TSFlags{63} = isRegisterLoad;
>>> > > let TSFlags{62} = isRegisterStore;
>>> > >}
>>> > >diff --git a/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp b/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
>>> > >new file mode 100644
>>> > >index 0000000..7331e7e
>>> > >--- /dev/null
>>> > >+++ b/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
>>> > >@@ -0,0 +1,224 @@
>>> > >+//===-- AMDGPUAsmParser.cpp - Parse R600 asm to MCInst instructions ---------===//
>> >Should this really be SIAsmParser?
>> >
> TableGen expects the class to be called AMDGPUAsmParser.cpp, but I changed the
> comment from R600 asm to SI asm.
>
> The attached patches addresses your other concerns and implements the
> parser for all sopp instructions including the special syntax for
> s_waitcnt.
>
> -Tom
LGTM
>
> 0001-R600-SI-Start-implementing-an-assembler.patch
>
>
> From 3b94fbc540c32a42a340b39f6ae3725056e335a1 Mon Sep 17 00:00:00 2001
> From: Tom Stellard<thomas.stellard at amd.com>
> Date: Wed, 5 Nov 2014 21:32:56 -0500
> Subject: [PATCH] R600/SI: Start implementing an assembler
>
> This was done using the Sparc and PowerPC AsmParsers as guides. So far it
> is very simple and only supports sopp instructions.
> ---
> docs/R600Usage.rst | 43 ++++
> docs/index.rst | 4 +
> lib/Target/R600/AMDGPU.td | 7 +
> lib/Target/R600/AMDGPUInstructions.td | 2 +
> lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp | 319 ++++++++++++++++++++++++++
> lib/Target/R600/AsmParser/CMakeLists.txt | 3 +
> lib/Target/R600/AsmParser/LLVMBuild.txt | 23 ++
> lib/Target/R600/AsmParser/Makefile | 15 ++
> lib/Target/R600/CMakeLists.txt | 2 +
> lib/Target/R600/LLVMBuild.txt | 5 +-
> lib/Target/R600/Makefile | 4 +-
> lib/Target/R600/R600InstrFormats.td | 3 +
> lib/Target/R600/R600Instructions.td | 1 +
> lib/Target/R600/SIInstrFormats.td | 3 +-
> lib/Target/R600/SIInstructions.td | 55 +++--
> test/MC/R600/lit.local.cfg | 2 +
> test/MC/R600/sopp.s | 52 +++++
> 17 files changed, 513 insertions(+), 30 deletions(-)
> create mode 100644 docs/R600Usage.rst
> create mode 100644 lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
> create mode 100644 lib/Target/R600/AsmParser/CMakeLists.txt
> create mode 100644 lib/Target/R600/AsmParser/LLVMBuild.txt
> create mode 100644 lib/Target/R600/AsmParser/Makefile
> create mode 100644 test/MC/R600/lit.local.cfg
> create mode 100644 test/MC/R600/sopp.s
>
> diff --git a/docs/R600Usage.rst b/docs/R600Usage.rst
> new file mode 100644
> index 0000000..48a30c8
> --- /dev/null
> +++ b/docs/R600Usage.rst
> @@ -0,0 +1,43 @@
> +============================
> +User Guide for R600 Back-end
> +============================
> +
> +Introduction
> +============
> +
> +The R600 back-end provides ISA code generation for AMD GPUs, starting with
> +the R600 family up until the current Sea Islands (GCN Gen 2).
> +
> +
> +Assembler
> +=========
> +
> +The assembler is currently a work in progress and not yet complete. Below
> +are the currently supported features.
> +
> +SOPP Instructions
> +-----------------
> +
> +Unless otherwise mentioned, all SOPP instructions that with an operand
> +accept a integer operand(s) only. No verification is performed on the
> +operands, so it is up to the programmer to be familiar with the range
> +or acceptable values.
> +
> +s_waitcnt
> +^^^^^^^^^
> +
> +s_waitcnt accepts named arguments to specify which memory counter(s) to
> +wait for.
> +
> +.. code-block:: nasm
> +
> + // Wait for all counters to be 0
> + s_waitcnt 0
> +
> + // Equivalent to s_waitcnt 0. Counter names can also be delimited by
> + // '&' or ','.
> + s_waitcnt vmcnt(0) expcnt(0) lgkcmt(0)
> +
> + // Wait for vmcnt counter to be 1.
> + s_waitcnt vmcnt(1)
> +
> diff --git a/docs/index.rst b/docs/index.rst
> index 403c17a..5ac5443 100644
> --- a/docs/index.rst
> +++ b/docs/index.rst
> @@ -235,6 +235,7 @@ For API clients and LLVM developers.
> WritingAnLLVMPass
> HowToUseAttributes
> NVPTXUsage
> + R600Usage
> StackMaps
> InAlloca
> BigEndianNEON
> @@ -317,6 +318,9 @@ For API clients and LLVM developers.
> :doc:`NVPTXUsage`
> This document describes using the NVPTX back-end to compile GPU kernels.
>
> +:doc:`R600Usage`
> + This document describes how to use the R600 back-end.
> +
> :doc:`StackMaps`
> LLVM support for mapping instruction addresses to the location of
> values and allowing code to be patched.
> diff --git a/lib/Target/R600/AMDGPU.td b/lib/Target/R600/AMDGPU.td
> index f5930f5..4cf1243 100644
> --- a/lib/Target/R600/AMDGPU.td
> +++ b/lib/Target/R600/AMDGPU.td
> @@ -153,9 +153,16 @@ def AMDGPUInstrInfo : InstrInfo {
> let guessInstructionProperties = 1;
> }
>
> +def AMDGPUAsmParser : AsmParser {
> + // Some of the R600 registers have the same name, so this crashes.
> + // For example T0_XYZW and T0_XY both have the asm name T0.
> + let ShouldEmitMatchRegisterName = 0;
> +}
> +
> def AMDGPU : Target {
> // Pull in Instruction Info:
> let InstructionSet = AMDGPUInstrInfo;
> + let AssemblyParsers = [AMDGPUAsmParser];
> }
>
> // Dummy Instruction itineraries for pseudo instructions
> diff --git a/lib/Target/R600/AMDGPUInstructions.td b/lib/Target/R600/AMDGPUInstructions.td
> index ba5630e..c215865 100644
> --- a/lib/Target/R600/AMDGPUInstructions.td
> +++ b/lib/Target/R600/AMDGPUInstructions.td
> @@ -23,6 +23,8 @@ class AMDGPUInst <dag outs, dag ins, string asm, list<dag> pattern> : Instructio
> let Pattern = pattern;
> let Itinerary = NullALU;
>
> + let isCodeGenOnly = 1;
> +
> let TSFlags{63} = isRegisterLoad;
> let TSFlags{62} = isRegisterStore;
> }
> diff --git a/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp b/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
> new file mode 100644
> index 0000000..205de5f
> --- /dev/null
> +++ b/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
> @@ -0,0 +1,319 @@
> +//===-- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/ADT/SmallString.h"
> +#include "llvm/ADT/SmallVector.h"
STLExtras comes after these
> +#include "llvm/ADT/StringSwitch.h"
> +#include "llvm/ADT/Twine.h"
> +#include "llvm/MC/MCContext.h"
> +#include "llvm/MC/MCExpr.h"
> +#include "llvm/MC/MCInst.h"
> +#include "llvm/MC/MCInstrInfo.h"
> +#include "llvm/MC/MCParser/MCAsmLexer.h"
> +#include "llvm/MC/MCParser/MCAsmParser.h"
> +#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
> +#include "llvm/MC/MCRegisterInfo.h"
> +#include "llvm/MC/MCStreamer.h"
> +#include "llvm/MC/MCSubtargetInfo.h"
> +#include "llvm/MC/MCTargetAsmParser.h"
> +#include "llvm/Support/SourceMgr.h"
> +#include "llvm/Support/TargetRegistry.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +using namespace llvm;
> +
> +namespace {
> +
> +class AMDGPUAsmParser : public MCTargetAsmParser {
> + MCSubtargetInfo &STI;
> + MCAsmParser &Parser;
> +
> +
> + /// @name Auto-generated Match Functions
> + /// {
> +
> +#define GET_ASSEMBLER_HEADER
> +#include "AMDGPUGenAsmMatcher.inc"
> +
> + /// }
> +
> +public:
> + AMDGPUAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser,
> + const MCInstrInfo &_MII,
> + const MCTargetOptions &Options)
> + : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
> + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
> + }
> + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
> + bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
> + OperandVector &Operands, MCStreamer &Out,
> + uint64_t &ErrorInfo,
> + bool MatchingInlineAsm) override;
> + bool ParseDirective(AsmToken DirectiveID) override;
> + OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
> + bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
> + SMLoc NameLoc, OperandVector &Operands) override;
> +
> + bool parseCnt(int64_t &IntVal);
> + OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
> +};
> +
> +class AMDGPUOperand : public MCParsedAsmOperand {
> + enum KindTy {
> + Token,
> + Immediate
> + } Kind;
> +
> +public:
> + AMDGPUOperand(enum KindTy K) : MCParsedAsmOperand(), Kind(K) {}
> +
> + struct TokOp {
> + const char *Data;
> + unsigned Length;
> + };
> +
> + struct ImmOp {
> + int64_t Val;
> + };
> +
> + union {
> + TokOp Tok;
> + ImmOp Imm;
> + };
> +
> + void addImmOperands(MCInst &Inst, unsigned N) const {
> + Inst.addOperand(MCOperand::CreateImm(getImm()));
> + }
> + void addRegOperands(MCInst &Inst, unsigned N) const {
> + llvm_unreachable("addRegOperands");
> + }
> + StringRef getToken() const {
> + return StringRef(Tok.Data, Tok.Length);
> + }
> + bool isToken() const override {
> + return Kind == Token;
> + }
> +
> + bool isImm() const override {
> + return Kind == Immediate;
> + }
> +
> + int64_t getImm() const {
> + return Imm.Val;
> + }
> +
> + bool isReg() const override {
> + return false;
> + }
> +
> + unsigned getReg() const override {
> + return 0;
> + }
> +
> + bool isMem() const override {
> + return false;
> + }
> +
> + SMLoc getStartLoc() const override {
> + return SMLoc();
> + }
> +
> + SMLoc getEndLoc() const override {
> + return SMLoc();
> + }
> +
> + void print(raw_ostream &OS) const override { }
> +
> + static std::unique_ptr<AMDGPUOperand> CreateImm(int64_t Val) {
> + auto Op = llvm::make_unique<AMDGPUOperand>(Immediate);
> + Op->Imm.Val = Val;
> + return Op;
> + }
> +
> + static std::unique_ptr<AMDGPUOperand> CreateToken(StringRef Str, SMLoc Loc) {
> + auto Res = llvm::make_unique<AMDGPUOperand>(Token);
> + Res->Tok.Data = Str.data();
> + Res->Tok.Length = Str.size();
> + return Res;
> + }
> +
> + bool isSWaitCnt() const;
> +};
> +
> +}
> +
> +bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
> + return true;
> +}
> +
> +
> +bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
> + OperandVector &Operands,
> + MCStreamer &Out,
> + uint64_t &ErrorInfo,
> + bool MatchingInlineAsm) {
> + MCInst Inst;
> +
> + switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
> + default: break;
> + case Match_Success:
> + Inst.setLoc(IDLoc);
> + Out.EmitInstruction(Inst, STI);
> + return false;
> + case Match_MissingFeature:
> + return Error(IDLoc, "instruction use requires an option to be enabled");
> + case Match_MnemonicFail:
> + return Error(IDLoc, "unrecognized instruction mnemonic");
> + case Match_InvalidOperand: {
> + if (ErrorInfo != ~0ULL) {
> + if (ErrorInfo >= Operands.size())
> + return Error(IDLoc, "too few operands for instruction");
> +
> + }
> + return Error(IDLoc, "invalid operand for instruction");
> + }
> + }
> + llvm_unreachable("Implement any new match types added!");
> +}
> +
> +bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
> + return true;
> +}
> +
> +AMDGPUAsmParser::OperandMatchResultTy
> +AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
> +
> + // Try to parse with a custom parser
> + OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
> +
> + // If we successfully parsed the operand or if there as an error parsing,
> + // we are done.
> + if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
> + return ResTy;
> +
> + switch(getLexer().getKind()) {
> + case AsmToken::Integer: {
> + int64_t IntVal;
> + if (getParser().parseAbsoluteExpression(IntVal))
> + return MatchOperand_ParseFail;
> + Operands.push_back(AMDGPUOperand::CreateImm(IntVal));
> + return MatchOperand_Success;
> + }
> + default:
> + return MatchOperand_NoMatch;
> + }
> +}
> +
> +bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
> + StringRef Name,
> + SMLoc NameLoc, OperandVector &Operands) {
> + // Add the instruction mnemonic
> + Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc));
> +
> + if (getLexer().is(AsmToken::EndOfStatement))
> + return false;
> +
> + AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name);
> + switch (Res) {
> + case MatchOperand_Success: return false;
> + case MatchOperand_ParseFail: return Error(NameLoc,
> + "Failed parsing operand");
> + case MatchOperand_NoMatch: return Error(NameLoc, "Not a valid operand");
> + }
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// s_waitcnt
> +//===----------------------------------------------------------------------===//
> +
> +bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
> + StringRef CntName = Parser.getTok().getString();
> + int64_t CntVal;
> +
> + Parser.Lex();
> + if (getLexer().isNot(AsmToken::LParen))
> + return true;
> +
> + Parser.Lex();
> + if (getLexer().isNot(AsmToken::Integer))
> + return true;
> +
> + if (getParser().parseAbsoluteExpression(CntVal))
> + return true;
> +
> + if (getLexer().isNot(AsmToken::RParen))
> + return true;
> +
> + Parser.Lex();
> + if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma))
> + Parser.Lex();
> +
> + int CntShift;
> + int CntMask;
> +
> + if (CntName == "vmcnt") {
> + CntMask = 0xf;
> + CntShift = 0;
> + } else if (CntName == "expcnt") {
> + CntMask = 0x7;
> + CntShift = 4;
> + } else if (CntName == "lgkmcnt") {
> + CntMask = 0x7;
> + CntShift = 8;
> + } else {
> + return true;
> + }
> +
> + IntVal &= ~(CntMask << CntShift);
> + IntVal |= (CntVal << CntShift);
> + return false;
> +}
> +
> +AMDGPUAsmParser::OperandMatchResultTy
> +AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
> + // Disable all counters by default.
> + // vmcnt [3:0]
> + // expcnt [6:4]
> + // lgkmcnt [10:8]
> + int64_t CntVal = 0x77f;
> +
> + switch(getLexer().getKind()) {
> + default: return MatchOperand_ParseFail;
> + case AsmToken::Integer:
> + // The operand can be an integer value.
> + if (getParser().parseAbsoluteExpression(CntVal))
> + return MatchOperand_ParseFail;
> + break;
> +
> + case AsmToken::Identifier:
> + do {
> + if (parseCnt(CntVal))
> + return MatchOperand_ParseFail;
> + } while(getLexer().isNot(AsmToken::EndOfStatement));
> + break;
> + }
> + Operands.push_back(AMDGPUOperand::CreateImm(CntVal));
> + return MatchOperand_Success;
> +}
> +
> +bool AMDGPUOperand::isSWaitCnt() const {
> + return isImm();
> +}
> +
> +/// Force static initialization.
> +extern "C" void LLVMInitializeR600AsmParser() {
> + RegisterMCAsmParser<AMDGPUAsmParser> A(TheAMDGPUTarget);
> +}
> +
> +#define GET_REGISTER_MATCHER
> +#define GET_MATCHER_IMPLEMENTATION
> +#include "AMDGPUGenAsmMatcher.inc"
> +
> diff --git a/lib/Target/R600/AsmParser/CMakeLists.txt b/lib/Target/R600/AsmParser/CMakeLists.txt
> new file mode 100644
> index 0000000..1b42af7
> --- /dev/null
> +++ b/lib/Target/R600/AsmParser/CMakeLists.txt
> @@ -0,0 +1,3 @@
> +add_llvm_library(LLVMR600AsmParser
> + AMDGPUAsmParser.cpp
> + )
> diff --git a/lib/Target/R600/AsmParser/LLVMBuild.txt b/lib/Target/R600/AsmParser/LLVMBuild.txt
> new file mode 100644
> index 0000000..940e4ce
> --- /dev/null
> +++ b/lib/Target/R600/AsmParser/LLVMBuild.txt
> @@ -0,0 +1,23 @@
> +;===- ./lib/Target/R600/AsmParser/LLVMBuild.txt -------------*- Conf -*--===;
> +;
> +; The LLVM Compiler Infrastructure
> +;
> +; This file is distributed under the University of Illinois Open Source
> +; License. See LICENSE.TXT for details.
> +;
> +;===------------------------------------------------------------------------===;
> +;
> +; This is an LLVMBuild description file for the components in this subdirectory.
> +;
> +; For more information on the LLVMBuild system, please see:
> +;
> +;http://llvm.org/docs/LLVMBuild.html
> +;
> +;===------------------------------------------------------------------------===;
> +
> +[component_0]
> +type = Library
> +name = R600AsmParser
> +parent = R600
> +required_libraries = MC MCParser R600Desc R600Info Support
> +add_to_library_groups = R600
> diff --git a/lib/Target/R600/AsmParser/Makefile b/lib/Target/R600/AsmParser/Makefile
> new file mode 100644
> index 0000000..e6689b5
> --- /dev/null
> +++ b/lib/Target/R600/AsmParser/Makefile
> @@ -0,0 +1,15 @@
> +##===- lib/Target/R600/AsmParser/Makefile ----------------*- Makefile -*-===##
> +#
> +# The LLVM Compiler Infrastructure
> +#
> +# This file is distributed under the University of Illinois Open Source
> +# License. See LICENSE.TXT for details.
> +#
> +##===----------------------------------------------------------------------===##
> +LEVEL = ../../../..
> +LIBRARYNAME = LLVMR600AsmParser
> +
> +# Hack: we need to include 'main' R600 target directory to grab private headers
> +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
> +
> +include $(LEVEL)/Makefile.common
> diff --git a/lib/Target/R600/CMakeLists.txt b/lib/Target/R600/CMakeLists.txt
> index 7dbff55..ed0a216 100644
> --- a/lib/Target/R600/CMakeLists.txt
> +++ b/lib/Target/R600/CMakeLists.txt
> @@ -9,6 +9,7 @@ tablegen(LLVM AMDGPUGenIntrinsics.inc -gen-tgt-intrinsic)
> tablegen(LLVM AMDGPUGenMCCodeEmitter.inc -gen-emitter)
> tablegen(LLVM AMDGPUGenDFAPacketizer.inc -gen-dfa-packetizer)
> tablegen(LLVM AMDGPUGenAsmWriter.inc -gen-asm-writer)
> +tablegen(LLVM AMDGPUGenAsmMatcher.inc -gen-asm-matcher)
> add_public_tablegen_target(AMDGPUCommonTableGen)
>
> add_llvm_target(R600CodeGen
> @@ -54,6 +55,7 @@ add_llvm_target(R600CodeGen
> SITypeRewriter.cpp
> )
>
> +add_subdirectory(AsmParser)
> add_subdirectory(InstPrinter)
> add_subdirectory(TargetInfo)
> add_subdirectory(MCTargetDesc)
> diff --git a/lib/Target/R600/LLVMBuild.txt b/lib/Target/R600/LLVMBuild.txt
> index 1b0472a..f3f254f 100644
> --- a/lib/Target/R600/LLVMBuild.txt
> +++ b/lib/Target/R600/LLVMBuild.txt
> @@ -16,17 +16,18 @@
> ;===------------------------------------------------------------------------===;
>
> [common]
> -subdirectories = InstPrinter MCTargetDesc TargetInfo
> +subdirectories = AsmParser InstPrinter MCTargetDesc TargetInfo
>
> [component_0]
> type = TargetGroup
> name = R600
> parent = Target
> +has_asmparser = 1
> has_asmprinter = 1
>
> [component_1]
> type = Library
> name = R600CodeGen
> parent = R600
> -required_libraries = Analysis AsmPrinter CodeGen Core IPO MC R600AsmPrinter R600Desc R600Info Scalar SelectionDAG Support Target TransformUtils
> +required_libraries = Analysis AsmPrinter CodeGen Core IPO MC R600AsmParser R600AsmPrinter R600Desc R600Info Scalar SelectionDAG Support Target TransformUtils
> add_to_library_groups = R600
> diff --git a/lib/Target/R600/Makefile b/lib/Target/R600/Makefile
> index 1b3ebbe..64a7c8c 100644
> --- a/lib/Target/R600/Makefile
> +++ b/lib/Target/R600/Makefile
> @@ -16,8 +16,8 @@ BUILT_SOURCES = AMDGPUGenRegisterInfo.inc AMDGPUGenInstrInfo.inc \
> AMDGPUGenDAGISel.inc AMDGPUGenSubtargetInfo.inc \
> AMDGPUGenMCCodeEmitter.inc AMDGPUGenCallingConv.inc \
> AMDGPUGenIntrinsics.inc AMDGPUGenDFAPacketizer.inc \
> - AMDGPUGenAsmWriter.inc
> + AMDGPUGenAsmWriter.inc AMDGPUGenAsmMatcher.inc
>
> -DIRS = InstPrinter TargetInfo MCTargetDesc
> +DIRS = AsmParser InstPrinter TargetInfo MCTargetDesc
>
> include $(LEVEL)/Makefile.common
> diff --git a/lib/Target/R600/R600InstrFormats.td b/lib/Target/R600/R600InstrFormats.td
> index 9428bab..0ffd485 100644
> --- a/lib/Target/R600/R600InstrFormats.td
> +++ b/lib/Target/R600/R600InstrFormats.td
> @@ -38,6 +38,9 @@ class InstR600 <dag outs, dag ins, string asm, list<dag> pattern,
> let Pattern = pattern;
> let Itinerary = itin;
>
> + // No AsmMatcher support.
> + let isCodeGenOnly = 1;
> +
> let TSFlags{4} = Trig;
> let TSFlags{5} = Op3;
>
> diff --git a/lib/Target/R600/R600Instructions.td b/lib/Target/R600/R600Instructions.td
> index 7ce05a2..fbcca54 100644
> --- a/lib/Target/R600/R600Instructions.td
> +++ b/lib/Target/R600/R600Instructions.td
> @@ -1495,6 +1495,7 @@ class ILFormat<dag outs, dag ins, string asmstr, list<dag> pattern>
> let mayLoad = 0;
> let mayStore = 0;
> let hasSideEffects = 0;
> + let isCodeGenOnly = 1;
> }
>
> multiclass BranchConditional<SDNode Op, RegisterClass rci, RegisterClass rcf> {
> diff --git a/lib/Target/R600/SIInstrFormats.td b/lib/Target/R600/SIInstrFormats.td
> index 18c1345..bc8c011 100644
> --- a/lib/Target/R600/SIInstrFormats.td
> +++ b/lib/Target/R600/SIInstrFormats.td
> @@ -204,12 +204,13 @@ class SOPK <bits<5> op, dag outs, dag ins, string asm, list<dag> pattern> :
> let UseNamedOperandTable = 1;
> }
>
> -class SOPP <bits<7> op, dag ins, string asm, list<dag> pattern> :
> +class SOPP <bits<7> op, dag ins, string asm, list<dag> pattern = []> :
> InstSI <(outs), ins, asm, pattern >, SOPPe <op> {
>
> let mayLoad = 0;
> let mayStore = 0;
> let hasSideEffects = 0;
> + let isCodeGenOnly = 0;
> let SALU = 1;
>
> let UseNamedOperandTable = 1;
> diff --git a/lib/Target/R600/SIInstructions.td b/lib/Target/R600/SIInstructions.td
> index 3842f84..a082736 100644
> --- a/lib/Target/R600/SIInstructions.td
> +++ b/lib/Target/R600/SIInstructions.td
> @@ -33,7 +33,15 @@ def isCI : Predicate<"Subtarget.getGeneration() "
> ">= AMDGPUSubtarget::SEA_ISLANDS">;
> def HasFlatAddressSpace : Predicate<"Subtarget.hasFlatAddressSpace()">;
>
> -def WAIT_FLAG : InstFlag<"printWaitFlag">;
> +def SWaitMatchClass : AsmOperandClass {
> + let Name = "SWaitCnt";
> + let RenderMethod = "addImmOperands";
> + let ParserMethod = "parseSWaitCntOps";
> +}
> +
> +def WAIT_FLAG : InstFlag<"printWaitFlag"> {
> + let ParserMatchClass = SWaitMatchClass;
> +}
>
> let SubtargetPredicate = isSI in {
>
> @@ -372,7 +380,7 @@ def S_GETREG_REGRD_B32 : SOPK_32 <0x00000014, "s_getreg_regrd_b32", []>;
> // SOPP Instructions
> //===----------------------------------------------------------------------===//
>
> -def S_NOP : SOPP <0x00000000, (ins i16imm:$simm16), "s_nop $simm16", []>;
> +def S_NOP : SOPP <0x00000000, (ins i16imm:$simm16), "s_nop $simm16">;
>
> let isTerminator = 1 in {
>
> @@ -393,36 +401,31 @@ def S_BRANCH : SOPP <
> let DisableEncoding = "$scc" in {
> def S_CBRANCH_SCC0 : SOPP <
> 0x00000004, (ins sopp_brtarget:$simm16, SCCReg:$scc),
> - "s_cbranch_scc0 $simm16", []
> + "s_cbranch_scc0 $simm16"
> >;
> def S_CBRANCH_SCC1 : SOPP <
> 0x00000005, (ins sopp_brtarget:$simm16, SCCReg:$scc),
> - "s_cbranch_scc1 $simm16",
> - []
> + "s_cbranch_scc1 $simm16"
> >;
> } // End DisableEncoding = "$scc"
>
> def S_CBRANCH_VCCZ : SOPP <
> 0x00000006, (ins sopp_brtarget:$simm16, VCCReg:$vcc),
> - "s_cbranch_vccz $simm16",
> - []
> + "s_cbranch_vccz $simm16"
> >;
> def S_CBRANCH_VCCNZ : SOPP <
> 0x00000007, (ins sopp_brtarget:$simm16, VCCReg:$vcc),
> - "s_cbranch_vccnz $simm16",
> - []
> + "s_cbranch_vccnz $simm16"
> >;
>
> let DisableEncoding = "$exec" in {
> def S_CBRANCH_EXECZ : SOPP <
> 0x00000008, (ins sopp_brtarget:$simm16, EXECReg:$exec),
> - "s_cbranch_execz $simm16",
> - []
> + "s_cbranch_execz $simm16"
> >;
> def S_CBRANCH_EXECNZ : SOPP <
> 0x00000009, (ins sopp_brtarget:$simm16, EXECReg:$exec),
> - "s_cbranch_execnz $simm16",
> - []
> + "s_cbranch_execnz $simm16"
> >;
> } // End DisableEncoding = "$exec"
>
> @@ -441,12 +444,10 @@ def S_BARRIER : SOPP <0x0000000a, (ins), "s_barrier",
> let mayStore = 1;
> }
>
> -def S_WAITCNT : SOPP <0x0000000c, (ins WAIT_FLAG:$simm16), "s_waitcnt $simm16",
> - []
> ->;
> -//def S_SETHALT : SOPP_ <0x0000000d, "s_sethalt", []>;
> -//def S_SLEEP : SOPP_ <0x0000000e, "s_sleep", []>;
> -//def S_SETPRIO : SOPP_ <0x0000000f, "s_setprio", []>;
> +def S_WAITCNT : SOPP <0x0000000c, (ins WAIT_FLAG:$simm16), "s_waitcnt $simm16">;
> +def S_SETHALT : SOPP <0x0000000d, (ins i16imm:$simm16), "s_sethalt $simm16">;
> +def S_SLEEP : SOPP <0x0000000e, (ins i16imm:$simm16), "s_sleep $simm16">;
> +def S_SETPRIO : SOPP <0x0000000f, (ins i16imm:$sim16), "s_setprio $sim16">;
>
> let Uses = [EXEC] in {
> def S_SENDMSG : SOPP <0x00000010, (ins SendMsgImm:$simm16, M0Reg:$m0), "s_sendmsg $simm16",
> @@ -456,12 +457,16 @@ let Uses = [EXEC] in {
> }
> } // End Uses = [EXEC]
>
> -//def S_SENDMSGHALT : SOPP_ <0x00000011, "s_sendmsghalt", []>;
> -//def S_TRAP : SOPP_ <0x00000012, "s_trap", []>;
> -//def S_ICACHE_INV : SOPP_ <0x00000013, "s_icache_inv", []>;
> -//def S_INCPERFLEVEL : SOPP_ <0x00000014, "s_incperflevel", []>;
> -//def S_DECPERFLEVEL : SOPP_ <0x00000015, "s_decperflevel", []>;
> -//def S_TTRACEDATA : SOPP_ <0x00000016, "s_ttracedata", []>;
> +def S_SENDMSGHALT : SOPP <0x00000011, (ins i16imm:$simm16), "s_sendmsghalt $simm16">;
> +def S_TRAP : SOPP <0x00000012, (ins i16imm:$simm16), "s_trap $simm16">;
> +def S_ICACHE_INV : SOPP <0x00000013, (ins), "s_icache_inv"> {
> + let simm16 = 0;
> +}
> +def S_INCPERFLEVEL : SOPP <0x00000014, (ins i16imm:$simm16), "s_incperflevel $simm16">;
> +def S_DECPERFLEVEL : SOPP <0x00000015, (ins i16imm:$simm16), "s_decperflevel $simm16">;
> +def S_TTRACEDATA : SOPP <0x00000016, (ins), "s_ttracedata"> {
> + let simm16 = 0;
> +}
> } // End hasSideEffects
>
> //===----------------------------------------------------------------------===//
> diff --git a/test/MC/R600/lit.local.cfg b/test/MC/R600/lit.local.cfg
> new file mode 100644
> index 0000000..ad9ce25
> --- /dev/null
> +++ b/test/MC/R600/lit.local.cfg
> @@ -0,0 +1,2 @@
> +if not 'R600' in config.root.targets:
> + config.unsupported = True
> diff --git a/test/MC/R600/sopp.s b/test/MC/R600/sopp.s
> new file mode 100644
> index 0000000..65fc97b
> --- /dev/null
> +++ b/test/MC/R600/sopp.s
> @@ -0,0 +1,52 @@
> +// RUN: llvm-mc -arch=r600 -mcpu=SI -show-encoding %s | FileCheck %s
> +
> + s_nop 1 // CHECK: s_nop 1 ; encoding: [0x01,0x00,0x80,0xbf]
> + s_endpgm // CHECK: s_endpgm ; encoding: [0x00,0x00,0x81,0xbf]
> + s_branch 2 // CHECK: s_branch 2 ; encoding: [0x02,0x00,0x82,0xbf]
> + s_cbranch_scc0 3 // CHECK: s_cbranch_scc0 3 ; encoding: [0x03,0x00,0x84,0xbf]
> + s_cbranch_scc1 4 // CHECK: s_cbranch_scc1 4 ; encoding: [0x04,0x00,0x85,0xbf]
> + s_cbranch_vccz 5 // CHECK: s_cbranch_vccz 5 ; encoding: [0x05,0x00,0x86,0xbf]
> + s_cbranch_vccnz 6 // CHECK: s_cbranch_vccnz 6 ; encoding: [0x06,0x00,0x87,0xbf]
> + s_cbranch_execz 7 // CHECK: s_cbranch_execz 7 ; encoding: [0x07,0x00,0x88,0xbf]
> + s_cbranch_execnz 8 // CHECK: s_cbranch_execnz 8 ; encoding: [0x08,0x00,0x89,0xbf]
> + s_barrier // CHECK: s_barrier ; encoding: [0x00,0x00,0x8a,0xbf]
> +
> +//===----------------------------------------------------------------------===//
> +// s_waitcnt
> +//===----------------------------------------------------------------------===//
> +
> + s_waitcnt 0
> + // CHECK: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; encoding: [0x00,0x00,0x8c,0xbf]
> +
> + s_waitcnt vmcnt(0) & expcnt(0) & lgkmcnt(0)
> + // CHECK: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; encoding: [0x00,0x00,0x8c,0xbf]
> +
> + s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
> + // CHECK: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; encoding: [0x00,0x00,0x8c,0xbf]
> +
> + s_waitcnt vmcnt(0), expcnt(0), lgkmcnt(0)
> + // CHECK: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; encoding: [0x00,0x00,0x8c,0xbf]
> +
> + s_waitcnt vmcnt(1)
> + // CHECK: s_waitcnt vmcnt(1) ; encoding: [0x71,0x07,0x8c,0xbf]
> +
> + s_waitcnt expcnt(2)
> + // CHECK: s_waitcnt expcnt(2) ; encoding: [0x2f,0x07,0x8c,0xbf]
> +
> + s_waitcnt lgkmcnt(3)
> + // CHECK: s_waitcnt lgkmcnt(3) ; encoding: [0x7f,0x03,0x8c,0xbf]
> +
> + s_waitcnt vmcnt(0), expcnt(0)
> + // CHECK: s_waitcnt vmcnt(0) expcnt(0) ; encoding: [0x00,0x07,0x8c,0xbf]
> +
> +
> + s_sethalt 9 // CHECK: s_sethalt 9 ; encoding: [0x09,0x00,0x8d,0xbf]
> + s_sleep 10 // CHECK: s_sleep 10 ; encoding: [0x0a,0x00,0x8e,0xbf]
> + s_setprio 1 // CHECK: s_setprio 1 ; encoding: [0x01,0x00,0x8f,0xbf]
> + s_sendmsg 2 // CHECK: s_sendmsg Gs(nop), [m0] ; encoding: [0x02,0x00,0x90,0xbf]
> + s_sendmsghalt 3 // CHECK: s_sendmsghalt 3 ; encoding: [0x03,0x00,0x91,0xbf]
> + s_trap 4 // CHECK: s_trap 4 ; encoding: [0x04,0x00,0x92,0xbf]
> + s_icache_inv // CHECK: s_icache_inv ; encoding: [0x00,0x00,0x93,0xbf]
> + s_incperflevel 5 // CHECK: s_incperflevel 5 ; encoding: [0x05,0x00,0x94,0xbf]
> + s_decperflevel 6 // CHECK: s_decperflevel 6 ; encoding: [0x06,0x00,0x95,0xbf]
> + s_ttracedata // CHECK: s_ttracedata ; encoding: [0x00,0x00,0x96,0xbf]
> -- 1.8.1.5
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141112/fe865b7f/attachment.html>
More information about the llvm-commits
mailing list