Mesa (main): nir,docs: Add docs for NIR ALU instructions

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Jun 21 17:14:47 UTC 2021


Module: Mesa
Branch: main
Commit: 73188c6954299d57c5b3eb30c514977895283b66
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=73188c6954299d57c5b3eb30c514977895283b66

Author: Jason Ekstrand <jason at jlekstrand.net>
Date:   Fri Jun 18 08:16:18 2021 -0500

nir,docs: Add docs for NIR ALU instructions

About half or more of the text here is actually from Connor Abbot.  I've
edited it a bit to bring it up-to-date and make a few things more clear.

Reviewed-by: Connor Abbott <cwabbott0 at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11438>

---

 docs/doxygen-wrapper.py |  1 +
 docs/index.rst          |  1 +
 docs/nir/alu.rst        | 69 +++++++++++++++++++++++++++++++++++++++++++++++++
 docs/nir/index.rst      | 13 ++++++++++
 src/compiler/nir/nir.h  | 56 ++++++++++++++++++++++++++++++---------
 5 files changed, 128 insertions(+), 12 deletions(-)

diff --git a/docs/doxygen-wrapper.py b/docs/doxygen-wrapper.py
index 49735b3504c..090b5bcd757 100755
--- a/docs/doxygen-wrapper.py
+++ b/docs/doxygen-wrapper.py
@@ -29,6 +29,7 @@ import subprocess
 import tempfile
 
 INPUT_PATHS = [
+    'src/compiler/nir/nir.h',
     'src/intel/isl',
 ]
 
diff --git a/docs/index.rst b/docs/index.rst
index cbb5d6f8879..1cad5402dc9 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -111,6 +111,7 @@ Linux, FreeBSD, and other operating systems.
    release-calendar
    dispatch
    gallium/index
+   nir/index
    isl/index
    android
    macos
diff --git a/docs/nir/alu.rst b/docs/nir/alu.rst
new file mode 100644
index 00000000000..315b99cf29e
--- /dev/null
+++ b/docs/nir/alu.rst
@@ -0,0 +1,69 @@
+NIR ALU Instructions
+====================
+
+ALU instructions represent simple operations, such as addition, multiplication,
+comparison, etc., that take a certain number of arguments and return a result
+that only depends on the arguments.  ALU instructions in NIR must be pure in
+the sense that they have no side effect and that identical inputs yields an
+identical output.  A good rule of thumb is that only things which can be
+constant folded should be ALU operations.  If it can't be constant folded, then
+it should probably be an intrinsic instead.
+
+Each ALU instruction has an opcode, which is a member of the :cpp:enum:`nir_op`
+enum, that describes what it does as well as how many arguments it takes.
+Associated with each opcode is an metadata structure,
+:cpp:struct:`nir_op_info`, which shows how many arguments the opcode takes,
+information about data types, and algebraic properties such as associativity
+and commutivity. The info structure for each opcode may be accessed through
+a global :cpp:var:`nir_op_infos` array that’s indexed by the opcode.
+
+ALU operations are typeless, meaning that they're only defined to convert
+a certain bit-pattern input to another bit-pattern output.  The only concrete
+notion of types for a NIR SSA value or register is that each value has a number
+of vector components and a bit-size.  How that data is interpreted is entirely
+controlled by the opcode.  NIR doesn't have opcodes for ``intBitsToFloat()``
+and friends because they are implicit.
+
+Even though ALU operations are typeless, each opcode also has an "ALU type"
+metadata for each of the sources and the destination which can be
+floating-point, boolean, integer, or unsigned integer.  The ALU type mainly
+helps back-ends which want to handle all conversion instructions, for instance,
+in a single switch case.  They're also important when a back-end requests the
+absolute value, negate, and saturate modifiers (not used by core NIR).  In that
+case, modifiers are interpreted with respect to the ALU type on the source or
+destination of the instruction.  In addition, if an operation takes a boolean
+argument, then the argument may be assumed to be either ``0`` for false or
+``~0`` (a.k.a ``-1``) for true even if it is not a 1-bit value.  If an
+operation’s result has a boolean type, then it may only produce only ``0`` or ``~0``.
+
+Most of the common ALU ops in NIR operate per-component, meaning that the
+operation is defined by what it does on a single scalar value and, when
+performed on vectors, it performs the same operation on each component.  Things
+like add, multiply, etc. fall into this category.  Per-component operations
+naturally scale to as many components as necessary.  Non-per-component ALU ops
+are things like :nir:alu-op:`vec4` or :nir:alu-op:`pack_64_2x32` where any
+given component in the result value may be a combination of any component in
+any source.  These ops have a number of destination components and a number of
+components required by each source which is fixed by the opcode.
+
+While most instruction types in NIR require vector sizes to perfectly match on
+inputs and outputs, ALU instruction sources have an additional
+:cpp:member:`nir_alu_src::swizzle` field which allows them to act on vectors
+which are not the native vector size of the instruction.  This is ideal for
+hardware with a native data type of :c:expr:`vec4` but also means that ALU
+instructions are often used (and required) for packing/unpacking vectors for
+use in other instruction types like intrinsics or texture ops.
+
+.. doxygenstruct:: nir_op_info
+    :members:
+
+.. doxygenvariable:: nir_op_infos
+
+.. doxygenstruct:: nir_alu_instr
+    :members:
+
+.. doxygenstruct:: nir_alu_src
+    :members:
+
+.. doxygenstruct:: nir_alu_dest
+    :members:
diff --git a/docs/nir/index.rst b/docs/nir/index.rst
new file mode 100644
index 00000000000..630ba011885
--- /dev/null
+++ b/docs/nir/index.rst
@@ -0,0 +1,13 @@
+NIR Intermediate Representation (NIR)
+=====================================
+
+The NIR Intermediate Representation (NIR) is the optimizing compiler stack that
+sits at the core of most Mesa drivers' shader compilers.  It consists of a set
+of enums and data structures that make up the IR as well as a suite of helper
+functions, optimization passes, and lowering passes for building a compiler
+stack.
+
+.. toctree::
+   :maxdepth: 2
+
+   alu
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 66aad033447..ca123a51a61 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -1026,6 +1026,7 @@ void nir_src_copy(nir_src *dest, const nir_src *src, void *instr_or_if);
 void nir_dest_copy(nir_dest *dest, const nir_dest *src, nir_instr *instr);
 
 typedef struct {
+   /** Base source */
    nir_src src;
 
    /**
@@ -1049,27 +1050,34 @@ typedef struct {
 
    /**
     * For each input component, says which component of the register it is
-    * chosen from. Note that which elements of the swizzle are used and which
-    * are ignored are based on the write mask for most opcodes - for example,
-    * a statement like "foo.xzw = bar.zyx" would have a writemask of 1101b and
-    * a swizzle of {2, x, 1, 0} where x means "don't care."
+    * chosen from.
+    *
+    * Note that which elements of the swizzle are used and which are ignored
+    * are based on the write mask for most opcodes - for example, a statement
+    * like "foo.xzw = bar.zyx" would have a writemask of 1101b and a swizzle
+    * of {2, 1, x, 0} where x means "don't care."
     */
    uint8_t swizzle[NIR_MAX_VEC_COMPONENTS];
 } nir_alu_src;
 
 typedef struct {
+   /** Base destination */
    nir_dest dest;
 
    /**
-    * \name saturate output modifier
+    * Saturate output modifier
     *
     * Only valid for opcodes that output floating-point numbers. Clamps the
     * output to between 0.0 and 1.0 inclusive.
     */
-
    bool saturate;
 
-   unsigned write_mask : NIR_MAX_VEC_COMPONENTS; /* ignored if dest.is_ssa is true */
+   /**
+    * Write-mask
+    *
+    * Ignored if dest.is_ssa is true
+    */
+   unsigned write_mask : NIR_MAX_VEC_COMPONENTS;
 } nir_alu_dest;
 
 /** NIR sized and unsized types
@@ -1336,6 +1344,10 @@ typedef enum {
     * sources.
     */
    NIR_OP_IS_2SRC_COMMUTATIVE = (1 << 0),
+
+   /**
+    * Operation is associative
+    */
    NIR_OP_IS_ASSOCIATIVE = (1 << 1),
 } nir_op_algebraic_property;
 
@@ -1344,9 +1356,11 @@ typedef enum {
  */
 #define NIR_ALU_MAX_INPUTS NIR_MAX_VEC_COMPONENTS
 
-typedef struct {
+typedef struct nir_op_info {
+   /** Name of the NIR ALU opcode */
    const char *name;
 
+   /** Number of inputs (sources) */
    uint8_t num_inputs;
 
    /**
@@ -1372,11 +1386,13 @@ typedef struct {
     * The type of vector that the instruction outputs. Note that the
     * staurate modifier is only allowed on outputs with the float type.
     */
-
    nir_alu_type output_type;
 
    /**
     * The number of components in each input
+    *
+    * See nir_op_infos::output_size for more detail about the relationship
+    * between input and output sizes.
     */
    uint8_t input_sizes[NIR_ALU_MAX_INPUTS];
 
@@ -1387,16 +1403,21 @@ typedef struct {
     */
    nir_alu_type input_types[NIR_ALU_MAX_INPUTS];
 
+   /** Algebraic properties of this opcode */
    nir_op_algebraic_property algebraic_properties;
 
-   /* Whether this represents a numeric conversion opcode */
+   /** Whether this represents a numeric conversion opcode */
    bool is_conversion;
 } nir_op_info;
 
+/** Metadata for each nir_op, indexed by opcode */
 extern const nir_op_info nir_op_infos[nir_num_opcodes];
 
 typedef struct nir_alu_instr {
+   /** Base instruction */
    nir_instr instr;
+
+   /** Opcode */
    nir_op op;
 
    /** Indicates that this ALU instruction generates an exact value
@@ -1410,13 +1431,24 @@ typedef struct nir_alu_instr {
    bool exact:1;
 
    /**
-    * Indicates that this instruction do not cause wrapping to occur, in the
-    * form of overflow or underflow.
+    * Indicates that this instruction doese not cause signed integer wrapping
+    * to occur, in the form of overflow or underflow.
     */
    bool no_signed_wrap:1;
+
+   /**
+    * Indicates that this instruction does not cause unsigned integer wrapping
+    * to occur, in the form of overflow or underflow.
+    */
    bool no_unsigned_wrap:1;
 
+   /** Destination */
    nir_alu_dest dest;
+
+   /** Sources
+    *
+    * The size of the array is given by nir_op_info::num_inputs.
+    */
    nir_alu_src src[];
 } nir_alu_instr;
 



More information about the mesa-commit mailing list