From 9d986d19d0412759ecb10c0d8752bb0276d5c5f8 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 22 Oct 2014 12:57:28 -0700 Subject: [PATCH] nir: Add a lower_vec_to_movs pass Reviewed-by: Connor Abbott --- src/glsl/Makefile.sources | 1 + src/glsl/nir/nir.h | 2 + src/glsl/nir/nir_lower_vec_to_movs.c | 96 ++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 src/glsl/nir/nir_lower_vec_to_movs.c diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources index 20bf272569c..d3b17bd35f6 100644 --- a/src/glsl/Makefile.sources +++ b/src/glsl/Makefile.sources @@ -24,6 +24,7 @@ NIR_FILES = \ $(GLSL_SRCDIR)/nir/nir_lower_samplers.cpp \ $(GLSL_SRCDIR)/nir/nir_lower_system_values.c \ $(GLSL_SRCDIR)/nir/nir_lower_variables_scalar.c \ + $(GLSL_SRCDIR)/nir/nir_lower_vec_to_movs.c \ $(GLSL_SRCDIR)/nir/nir_opcodes.c \ $(GLSL_SRCDIR)/nir/nir_opcodes.h \ $(GLSL_SRCDIR)/nir/nir_opt_copy_propagate.c \ diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h index 0ddd44a9905..5c303edb4c0 100644 --- a/src/glsl/nir/nir.h +++ b/src/glsl/nir/nir.h @@ -1286,6 +1286,8 @@ void nir_lower_variables_scalar(nir_shader *shader, bool lower_globals, void nir_remove_dead_variables(nir_shader *shader); +void nir_lower_vec_to_movs(nir_shader *shader); + void nir_lower_samplers(nir_shader *shader, struct gl_shader_program *shader_program, struct gl_program *prog); diff --git a/src/glsl/nir/nir_lower_vec_to_movs.c b/src/glsl/nir/nir_lower_vec_to_movs.c new file mode 100644 index 00000000000..a3120b66635 --- /dev/null +++ b/src/glsl/nir/nir_lower_vec_to_movs.c @@ -0,0 +1,96 @@ +/* + * Copyright © 2014 Intel Corporation + * + * 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. + * + * Authors: + * Jason Ekstrand (jason@jlekstrand.net) + * + */ + +#include "nir.h" + +/* + * Implements a simple pass that lowers vecN instructions to a series of + * moves with partial writes. + */ + +static bool +lower_vec_to_movs_block(nir_block *block, void *mem_ctx) +{ + nir_foreach_instr_safe(block, instr) { + if (instr->type != nir_instr_type_alu) + continue; + + nir_alu_instr *vec = (nir_alu_instr *)instr; + + switch (vec->op) { + case nir_op_vec2: + case nir_op_vec3: + case nir_op_vec4: + break; + default: + continue; /* The loop */ + } + + for (unsigned i = 0, src_idx = 0; i < 4; i++) { + if (!(vec->dest.write_mask & (1 << i))) + continue; + + assert(src_idx < nir_op_infos[vec->op].num_inputs); + + nir_alu_instr *mov = nir_alu_instr_create(mem_ctx, nir_op_imov); + mov->src[0].src = nir_src_copy(vec->src[src_idx].src, mem_ctx); + mov->src[0].negate = vec->src[src_idx].negate; + mov->src[0].abs = vec->src[src_idx].abs; + + /* We only care about the one swizzle */ + mov->src[0].swizzle[i] = vec->src[src_idx].swizzle[0]; + + mov->dest.dest = nir_dest_copy(vec->dest.dest, mem_ctx); + mov->dest.saturate = vec->dest.saturate; + mov->dest.write_mask = (1u << i); + + nir_instr_insert_before(&vec->instr, &mov->instr); + + src_idx++; + } + + nir_instr_remove(&vec->instr); + ralloc_free(vec); + } + + return true; +} + +static void +nir_lower_vec_to_movs_impl(nir_function_impl *impl) +{ + nir_foreach_block(impl, lower_vec_to_movs_block, ralloc_parent(impl)); +} + +void +nir_lower_vec_to_movs(nir_shader *shader) +{ + nir_foreach_overload(shader, overload) { + if (overload->impl) + nir_lower_vec_to_movs_impl(overload->impl); + } +}