Home | History | Annotate | Line # | Download | only in nir
      1  1.1  mrg New IR, or NIR, is an IR for Mesa intended to sit below GLSL IR and Mesa IR.
      2  1.1  mrg Its design inherits from the various IRs that Mesa has used in the past, as
      3  1.1  mrg well as Direct3D assembly, and it includes a few new ideas as well. It is a
      4  1.1  mrg flat (in terms of using instructions instead of expressions), typeless IR,
      5  1.1  mrg similar to TGSI and Mesa IR.  It also supports SSA (although it doesn't require
      6  1.1  mrg it).
      7  1.1  mrg 
      8  1.1  mrg Variables
      9  1.1  mrg =========
     10  1.1  mrg 
     11  1.1  mrg NIR includes support for source-level GLSL variables through a structure mostly
     12  1.1  mrg copied from GLSL IR. These will be used for linking and conversion from GLSL IR
     13  1.1  mrg (and later, from an AST), but for the most part, they will be lowered to
     14  1.1  mrg registers (see below) and loads/stores.
     15  1.1  mrg 
     16  1.1  mrg Registers
     17  1.1  mrg =========
     18  1.1  mrg 
     19  1.1  mrg Registers are light-weight; they consist of a structure that only contains its
     20  1.1  mrg size, its index for liveness analysis, and an optional name for debugging. In
     21  1.1  mrg addition, registers can be local to a function or global to the entire shader;
     22  1.1  mrg the latter will be used in ARB_shader_subroutine for passing parameters and
     23  1.1  mrg getting return values from subroutines. Registers can also be an array, in which
     24  1.1  mrg case they can be accessed indirectly. Each ALU instruction (add, subtract, etc.)
     25  1.1  mrg works directly with registers or SSA values (see below).
     26  1.1  mrg 
     27  1.1  mrg SSA
     28  1.1  mrg ========
     29  1.1  mrg 
     30  1.1  mrg Everywhere a register can be loaded/stored, an SSA value can be used instead.
     31  1.1  mrg The only exception is that arrays/indirect addressing are not supported with
     32  1.1  mrg SSA; although research has been done on extensions of SSA to arrays before, it's
     33  1.1  mrg usually for the purpose of parallelization (which we're not interested in), and
     34  1.1  mrg adds some overhead in the form of adding copies or extra arrays (which is much
     35  1.1  mrg more expensive than introducing copies between non-array registers). SSA uses
     36  1.1  mrg point directly to their corresponding definition, which in turn points to the
     37  1.1  mrg instruction it is part of. This creates an implicit use-def chain and avoids the
     38  1.1  mrg need for an external structure for each SSA register.
     39  1.1  mrg 
     40  1.1  mrg Functions
     41  1.1  mrg =========
     42  1.1  mrg 
     43  1.1  mrg Support for function calls is mostly similar to GLSL IR. Each shader contains a
     44  1.1  mrg list of functions, and each function has a list of overloads. Each overload
     45  1.1  mrg contains a list of parameters, and may contain an implementation which specifies
     46  1.1  mrg the variables that correspond to the parameters and return value. Inlining a
     47  1.1  mrg function, assuming it has a single return point, is as simple as copying its
     48  1.1  mrg instructions, registers, and local variables into the target function and then
     49  1.1  mrg inserting copies to and from the new parameters as appropriate. After functions
     50  1.1  mrg are inlined and any non-subroutine functions are deleted, parameters and return
     51  1.1  mrg variables will be converted to global variables and then global registers. We
     52  1.1  mrg don't do this lowering earlier (i.e. the fortranizer idea) for a few reasons:
     53  1.1  mrg 
     54  1.1  mrg - If we want to do optimizations before link time, we need to have the function
     55  1.1  mrg signature available during link-time.
     56  1.1  mrg 
     57  1.1  mrg - If we do any inlining before link time, then we might wind up with the
     58  1.1  mrg inlined function and the non-inlined function using the same global
     59  1.1  mrg variables/registers which would preclude optimization.
     60  1.1  mrg 
     61  1.1  mrg Intrinsics
     62  1.1  mrg =========
     63  1.1  mrg 
     64  1.1  mrg Any operation (other than function calls and textures) which touches a variable
     65  1.1  mrg or is not referentially transparent is represented by an intrinsic. Intrinsics
     66  1.1  mrg are similar to the idea of a "builtin function," i.e. a function declaration
     67  1.1  mrg whose implementation is provided by the backend, except they are more powerful
     68  1.1  mrg in the following ways:
     69  1.1  mrg 
     70  1.1  mrg - They can also load and store registers when appropriate, which limits the
     71  1.1  mrg number of variables needed in later stages of the IR while obviating the need
     72  1.1  mrg for a separate load/store variable instruction.
     73  1.1  mrg 
     74  1.1  mrg - Intrinsics can be marked as side-effect free, which permits them to be
     75  1.1  mrg treated like any other instruction when it comes to optimizations. This allows
     76  1.1  mrg load intrinsics to be represented as intrinsics while still being optimized
     77  1.1  mrg away by dead code elimination, common subexpression elimination, etc.
     78  1.1  mrg 
     79  1.1  mrg Intrinsics are used for:
     80  1.1  mrg 
     81  1.1  mrg - Atomic operations
     82  1.1  mrg - Memory barriers
     83  1.1  mrg - Subroutine calls
     84  1.1  mrg - Geometry shader emitVertex and endPrimitive
     85  1.1  mrg - Loading and storing variables (before lowering)
     86  1.1  mrg - Loading and storing uniforms, shader inputs and outputs, etc (after lowering)
     87  1.1  mrg - Copying variables (cases where in GLSL the destination is a structure or
     88  1.1  mrg array)
     89  1.1  mrg - The kitchen sink
     90  1.1  mrg - ...
     91  1.1  mrg 
     92  1.1  mrg Textures
     93  1.1  mrg =========
     94  1.1  mrg 
     95  1.1  mrg Unfortunately, there are far too many texture operations to represent each one
     96  1.1  mrg of them with an intrinsic, so there's a special texture instruction similar to
     97  1.1  mrg the GLSL IR one. The biggest difference is that, while the texture instruction
     98  1.1  mrg has a sampler dereference field used just like in GLSL IR, this gets lowered to
     99  1.1  mrg a texture unit index (with a possible indirect offset) while the type
    100  1.1  mrg information of the original sampler is kept around for backends. Also, all the
    101  1.1  mrg non-constant sources are stored in a single array to make it easier for
    102  1.1  mrg optimization passes to iterate over all the sources.
    103  1.1  mrg 
    104  1.1  mrg Control Flow
    105  1.1  mrg =========
    106  1.1  mrg 
    107  1.1  mrg Like in GLSL IR, control flow consists of a tree of "control flow nodes", which
    108  1.1  mrg include if statements and loops, and jump instructions (break, continue, and
    109  1.1  mrg return). Unlike GLSL IR, though, the leaves of the tree aren't statements but
    110  1.1  mrg basic blocks. Each basic block also keeps track of its successors and
    111  1.1  mrg predecessors, and function implementations keep track of the beginning basic
    112  1.1  mrg block (the first basic block of the function) and the ending basic block (a fake
    113  1.1  mrg basic block that every return statement points to). Together, these elements
    114  1.1  mrg make up the control flow graph, in this case a redundant piece of information on
    115  1.1  mrg top of the control flow tree that will be used by almost all the optimizations.
    116  1.1  mrg There are helper functions to add and remove control flow nodes that also update
    117  1.1  mrg the control flow graph, and so usually it doesn't need to be touched by passes
    118  1.1  mrg that modify control flow nodes.
    119