[Mesa-dev] [PATCH] nir: Add an ALU op builder kind of like ir_builder.h

Kenneth Graunke kenneth at whitecape.org
Sat Jan 31 03:09:32 PST 2015


On Friday, January 30, 2015 07:27:50 PM Connor Abbott wrote:
> I mentioned this on IRC, but it would be good to add the ability to
> append the sequence of instructions before/after an instruction as
> well as at the beginning or end of a basic block. We would need to
> store the current basic block, the current instruction, and an enum
> consisting of "insert before instruction," "insert after instruction,"
> insert at beginning of block," and "insert at end of block." Doing
> this would make the builder more useful for other places we currently
> create and insert ALU instruction manually -- just grep for
> nir_alu_instr_create(). Also, why isn't there a function for
> initializing the builder structure?
> 
> On Fri, Jan 30, 2015 at 4:07 PM, Eric Anholt <eric at anholt.net> wrote:
> > v2: Rebase on the nir_opcodes.h python code generation support.
> > v3: Use SSA values, and set an appropriate writemask on dot products.
> > v4: Make the arguments be SSA references as well.  This lets you stack up
> >     expressions in the arguments of other expressions, at the cost of
> >     having to insert a fmov/imov if you want to swizzle.  Also, add
> >     the generated file to NIR_GENERATED_FILES.
> > ---
> >  src/glsl/Makefile.am                  |  5 ++
> >  src/glsl/Makefile.sources             |  1 +
> >  src/glsl/nir/.gitignore               |  1 +
> >  src/glsl/nir/nir_builder.h            | 95 +++++++++++++++++++++++++++++++++++
> >  src/glsl/nir/nir_builder_opcodes_h.py | 38 ++++++++++++++
> >  5 files changed, 140 insertions(+)
> >  create mode 100644 src/glsl/nir/nir_builder.h
> >  create mode 100644 src/glsl/nir/nir_builder_opcodes_h.py
> >
> > diff --git a/src/glsl/Makefile.am b/src/glsl/Makefile.am
> > index e89a9ad..42c77ae 100644
> > --- a/src/glsl/Makefile.am
> > +++ b/src/glsl/Makefile.am
> > @@ -216,6 +216,7 @@ BUILT_SOURCES =                                             \
> >         glsl_lexer.cpp                                  \
> >         glcpp/glcpp-parse.c                             \
> >         glcpp/glcpp-lex.c                               \
> > +       nir/nir_builder_opcodes.h                               \
> >         nir/nir_constant_expressions.c                  \
> >         nir/nir_opcodes.c                               \
> >         nir/nir_opcodes.h                               \
> > @@ -232,6 +233,10 @@ dist-hook:
> >         $(RM) glcpp/tests/*.out
> >         $(RM) glcpp/tests/subtest*/*.out
> >
> > +nir/nir_builder_opcodes.h: nir/nir_opcodes.py nir/nir_builder_opcodes_h.py
> > +       $(MKDIR_P) nir;                                                 \
> > +       $(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/nir/nir_builder_opcodes_h.py > $@
> > +
> >  nir/nir_constant_expressions.c: nir/nir_opcodes.py nir/nir_constant_expressions.py nir/nir_constant_expressions.h
> >         $(MKDIR_P) nir;                                                 \
> >         $(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/nir/nir_constant_expressions.py > $@
> > diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources
> > index face22e..903f733 100644
> > --- a/src/glsl/Makefile.sources
> > +++ b/src/glsl/Makefile.sources
> > @@ -11,6 +11,7 @@ LIBGLCPP_GENERATED_FILES = \
> >         glcpp/glcpp-parse.c
> >
> >  NIR_GENERATED_FILES = \
> > +       nir/nir_builder_opcodes.h \
> >         nir/nir_constant_expressions.c \
> >         nir/nir_opcodes.c \
> >         nir/nir_opcodes.h \
> > diff --git a/src/glsl/nir/.gitignore b/src/glsl/nir/.gitignore
> > index 261f64f..64828eb 100644
> > --- a/src/glsl/nir/.gitignore
> > +++ b/src/glsl/nir/.gitignore
> > @@ -1,3 +1,4 @@
> > +nir_builder_opcodes.h
> >  nir_opt_algebraic.c
> >  nir_opcodes.c
> >  nir_opcodes.h
> > diff --git a/src/glsl/nir/nir_builder.h b/src/glsl/nir/nir_builder.h
> > new file mode 100644
> > index 0000000..50e8a20
> > --- /dev/null
> > +++ b/src/glsl/nir/nir_builder.h
> > @@ -0,0 +1,95 @@
> > +/*
> > + * Copyright © 2014-2015 Broadcom
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a
> > + * copy of this software and associated documentation files (the "Software"),
> > + * to deal in the Software without restriction, including without limitation
> > + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> > + * and/or sell copies of the Software, and to permit persons to whom the
> > + * Software is furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice (including the next
> > + * paragraph) shall be included in all copies or substantial portions of the
> > + * Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> > + * IN THE SOFTWARE.
> > + */
> > +
> > +#ifndef NIR_BUILDER_H
> > +#define NIR_BUILDER_H
> > +
> > +struct exec_list;
> > +
> > +struct nir_builder {
> > +   struct exec_list *cf_node_list;
> > +   nir_shader *shader;
> > +   nir_function_impl *impl;
> > +};
> > +
> > +static inline nir_ssa_def *
> > +nir_build_alu(struct nir_builder *build, nir_op op, nir_ssa_def *src0,
> > +              nir_ssa_def *src1, nir_ssa_def *src2, nir_ssa_def *src3)
> > +{
> > +   nir_alu_instr *instr = nir_alu_instr_create(build->shader, op);
> > +   if (!instr)
> > +      return NULL;
> > +
> > +   instr->src[0].src = nir_src_for_ssa(src0);
> > +   if (src1)
> > +      instr->src[1].src = nir_src_for_ssa(src1);
> > +   if (src2)
> > +      instr->src[2].src = nir_src_for_ssa(src2);
> > +   if (src3)
> > +      instr->src[3].src = nir_src_for_ssa(src3);
> > +
> > +   unsigned num_components = nir_op_infos[op].output_size;
> > +   if (num_components == 0)
> > +      num_components = 4;
> 
> We can and should do better here. We should look at the size
> (num_components) of the per-component (input_size == 0) inputs and
> make the output size the size of the largest input. Anything larger
> would be pointless.
> 
> > +
> > +   nir_ssa_dest_init(&instr->instr, &instr->dest.dest, num_components, NULL);
> > +   instr->dest.write_mask = (1 << num_components) - 1;
> > +
> > +   nir_instr_insert_after_cf_list(build->cf_node_list, &instr->instr);
> > +
> > +   return &instr->dest.dest.ssa;
> > +}
> > +
> > +#define ALU1(op)                                                          \
> > +static inline nir_ssa_def *                                               \
> > +nir_##op(struct nir_builder *build, nir_ssa_def *src0)                    \
> > +{                                                                         \
> > +   return nir_build_alu(build, nir_op_##op, src0, NULL, NULL, NULL);      \
> > +}
> > +
> > +#define ALU2(op)                                                          \
> > +static inline nir_ssa_def *                                               \
> > +nir_##op(struct nir_builder *build, nir_ssa_def *src0, nir_ssa_def *src1) \
> > +{                                                                         \
> > +   return nir_build_alu(build, nir_op_##op, src0, src1, NULL, NULL);      \
> > +}
> > +
> > +#define ALU3(op)                                                          \
> > +static inline nir_ssa_def *                                               \
> > +nir_##op(struct nir_builder *build, nir_ssa_def *src0,                    \
> > +         nir_ssa_def *src1, nir_ssa_def *src2)                            \
> > +{                                                                         \
> > +   return nir_build_alu(build, nir_op_##op, src0, src1, src2, NULL);      \
> > +}
> > +
> > +#define ALU4(op)                                                          \
> > +static inline nir_ssa_def *                                               \
> > +nir_##op(struct nir_builder *build, nir_ssa_def *src0,                    \
> > +         nir_ssa_def *src1, nir_ssa_def *src2, nir_ssa_def *src3)         \
> > +{                                                                         \
> > +   return nir_build_alu(build, nir_op_##op, src0, src1, src2, src3);      \
> > +}
> > +
> > +#include "nir_builder_opcodes.h"
> > +
> > +#endif /* NIR_BUILDER_H */
> > diff --git a/src/glsl/nir/nir_builder_opcodes_h.py b/src/glsl/nir/nir_builder_opcodes_h.py
> > new file mode 100644
> > index 0000000..e482339
> > --- /dev/null
> > +++ b/src/glsl/nir/nir_builder_opcodes_h.py
> > @@ -0,0 +1,38 @@
> > +#! /usr/bin/env python
> > +
> > +template = """\
> > +/* Copyright (C) 2015 Broadcom
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a
> > + * copy of this software and associated documentation files (the "Software"),
> > + * to deal in the Software without restriction, including without limitation
> > + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> > + * and/or sell copies of the Software, and to permit persons to whom the
> > + * Software is furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice (including the next
> > + * paragraph) shall be included in all copies or substantial portions of the
> > + * Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> > + * IN THE SOFTWARE.
> > + */
> > +
> > +#ifndef _NIR_BUILDER_OPCODES_
> > +#define _NIR_BUILDER_OPCODES_
> > +
> > +% for name in sorted(opcodes.iterkeys()):
> 
> - You don't need to use sorted() here, since unlike in nir_opcodes.h
> you don't care about the order.

That's true, but I still think it's worthwhile.  It means that you get
output that is consistently ordered from one run to the next, which makes
it much easier to save a copy of the output, change the generator, then
diff the output to ensure that your change did what you intended.

Without sorting, you get some random order.  Plus, it's a miniscule
amount of time during the Mesa build.  *shrug*

> - You should use "for name, opcode in opcodes.iteritems(opcodes)" and
> then use the opcode directly below instead of saying opcodes[name].

Agreed, that's the normal convention.

> > +ALU${opcodes[name].num_inputs}(${name});
> > +% endfor
> > +
> > +#endif /* _NIR_BUILDER_OPCODES_ */"""
> > +
> > +from nir_opcodes import opcodes
> > +from mako.template import Template
> > +
> > +print Template(template).render(opcodes=opcodes)
> > --
> > 2.1.4
> >
> > _______________________________________________
> > mesa-dev mailing list
> > mesa-dev at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/mesa-dev
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20150131/718b2836/attachment.sig>


More information about the mesa-dev mailing list