From 2a135c470e3db165a6417ffcccab4a9f4500f526 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Nov 2014 11:16:30 -0800 Subject: [PATCH] nir: Add an ALU op builder kind of like ir_builder.h 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. v5: Use more pythonish style for iterating the list. v6: Infer the size of the dest from the size of the srcs, and auto-swizzle a single small src out to the appropriate size. v7: Add little helpers for initializing the struct, add a typedef for the struct like other nir types have. Reviewed-by: Kenneth Graunke (v6) Reviewed-by: Connor Abbott (v7) --- src/glsl/Makefile.am | 5 ++ src/glsl/Makefile.sources | 1 + src/glsl/nir/.gitignore | 1 + src/glsl/nir/nir_builder.h | 130 ++++++++++++++++++++++++++++++++++ src/glsl/nir/nir_builder_opcodes_h.py | 38 ++++++++++ 5 files changed, 175 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 1e4d98f..5d5cacc 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 7e66e91..3157d9a 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..7c4f7fd --- /dev/null +++ b/src/glsl/nir/nir_builder.h @@ -0,0 +1,130 @@ +/* + * 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; + +typedef struct nir_builder { + struct exec_list *cf_node_list; + nir_shader *shader; + nir_function_impl *impl; +} nir_builder; + +static inline void +nir_builder_init(nir_builder *build, nir_function_impl *impl) +{ + memset(build, 0, sizeof(*build)); + build->impl = impl; + build->shader = impl->overload->function->shader; +} + +static inline void +nir_builder_insert_after_cf_list(nir_builder *build, + struct exec_list *cf_node_list) +{ + build->cf_node_list = cf_node_list; +} + + +static inline nir_ssa_def * +nir_build_alu(nir_builder *build, nir_op op, nir_ssa_def *src0, + nir_ssa_def *src1, nir_ssa_def *src2, nir_ssa_def *src3) +{ + const nir_op_info *op_info = &nir_op_infos[op]; + 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); + + /* Guess the number of components the destination temporary should have + * based on our input sizes, if it's not fixed for the op. + */ + unsigned num_components = op_info->output_size; + if (num_components == 0) { + for (unsigned i = 0; i < op_info->num_inputs; i++) { + if (op_info->input_sizes[i] == 0) + num_components = MAX2(num_components, + instr->src[i].src.ssa->num_components); + } + } + assert(num_components != 0); + + /* Make sure we don't swizzle from outside of our source vector (like if a + * scalar value was passed into a multiply with a vector). + */ + for (unsigned i = 0; i < op_info->num_inputs; i++) { + for (unsigned j = instr->src[i].src.ssa->num_components; j < 4; j++) { + instr->src[i].swizzle[j] = instr->src[i].src.ssa->num_components - 1; + } + } + + 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(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(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(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(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..e27206e --- /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, opcode in sorted(opcodes.iteritems()): +ALU${opcode.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.7.4