From: Rob Clark Date: Fri, 15 May 2020 23:14:47 +0000 (-0700) Subject: freedreno/ir3: add simple validate pass X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3561d34fff44ae82283dc1d4352e87d47793c40e;p=mesa.git freedreno/ir3: add simple validate pass We can add to this as we notice other things that are worth validating between ir3 passes. Signed-off-by: Rob Clark Part-of: --- diff --git a/src/freedreno/Makefile.sources b/src/freedreno/Makefile.sources index 43a8d2b5c1b..997d4311aa3 100644 --- a/src/freedreno/Makefile.sources +++ b/src/freedreno/Makefile.sources @@ -53,7 +53,8 @@ ir3_SOURCES := \ ir3/ir3_ra_regset.c \ ir3/ir3_sched.c \ ir3/ir3_shader.c \ - ir3/ir3_shader.h + ir3/ir3_shader.h \ + ir3/ir3_validate.c ir3_GENERATED_FILES := \ ir3/ir3_nir_trig.c \ diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index d039a4191a8..2fb21b67d4d 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -1183,11 +1183,16 @@ check_src_cond(struct ir3_instruction *instr, bool (*cond)(struct ir3_instructio #define IR3_PASS(ir, pass, ...) ({ \ bool progress = pass(ir, ##__VA_ARGS__); \ - if (progress) \ + if (progress) { \ ir3_debug_print(ir, "AFTER: " #pass); \ + ir3_validate(ir); \ + } \ progress; \ }) +/* validate: */ +void ir3_validate(struct ir3 *ir); + /* dump: */ void ir3_print(struct ir3 *ir); void ir3_print_instr(struct ir3_instruction *instr); diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index e0755086692..617fe1a7706 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -3586,6 +3586,7 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler, fixup_binning_pass(ctx); ir3_debug_print(ir, "AFTER: nir->ir3"); + ir3_validate(ir); do { progress = false; diff --git a/src/freedreno/ir3/ir3_validate.c b/src/freedreno/ir3/ir3_validate.c new file mode 100644 index 00000000000..422c9f49f6f --- /dev/null +++ b/src/freedreno/ir3/ir3_validate.c @@ -0,0 +1,129 @@ +/* + * Copyright © 2020 Google, Inc. + * + * 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. + */ + +#include + +#include "util/ralloc.h" + +#include "ir3.h" + +struct ir3_validate_ctx { + struct ir3 *ir; + + /* Current instruction being validated: */ + struct ir3_instruction *current_instr; + + /* Set of instructions found so far, used to validate that we + * don't have SSA uses that occure before def's + */ + struct set *defs; +}; + +static void +validate_error(struct ir3_validate_ctx *ctx, const char *condstr) +{ + fprintf(stderr, "validation fail: %s\n", condstr); + fprintf(stderr, " -> for instruction: "); + ir3_print_instr(ctx->current_instr); + abort(); +} + +#define validate_assert(ctx, cond) do { \ + if (!(cond)) { \ + validate_error(ctx, #cond); \ + } } while (0) + +static unsigned +reg_class_flags(struct ir3_register *reg) +{ + return reg->flags & (IR3_REG_HALF | IR3_REG_HIGH); +} + +static void +validate_src(struct ir3_validate_ctx *ctx, struct ir3_register *reg) +{ + struct ir3_instruction *src = ssa(reg); + + if (!src) + return; + + validate_assert(ctx, _mesa_set_search(ctx->defs, src)); + validate_assert(ctx, src->regs[0]->wrmask == reg->wrmask); + validate_assert(ctx, reg_class_flags(src->regs[0]) == reg_class_flags(reg)); +} + +static void +validate_instr(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr) +{ + struct ir3_register *last_reg = NULL; + + foreach_src_n (reg, n, instr) { + validate_src(ctx, reg); + + /* Validate that all src's are either half of full. + * + * Note: tex instructions w/ .s2en are a bit special in + * that the tex/samp src reg is half-reg irrespective of + * the precision of other srcs. The tex/samp src is the + * first src reg when .s2en is set + */ + if ((instr->flags & IR3_INSTR_S2EN) && (n < 2)) { + if (n == 0) { + validate_assert(ctx, reg->flags & IR3_REG_HALF); + } + } else if (n > 0) { + validate_assert(ctx, (last_reg->flags & IR3_REG_HALF) == (reg->flags & IR3_REG_HALF)); + } + + last_reg = reg; + } + + _mesa_set_add(ctx->defs, instr); +} + +void +ir3_validate(struct ir3 *ir) +{ +#ifdef NDEBUG +# define VALIDATE 0 +#else +# define VALIDATE 1 +#endif + + if (!VALIDATE) + return; + + struct ir3_validate_ctx *ctx = ralloc_size(NULL, sizeof(*ctx)); + + ctx->ir = ir; + ctx->defs = _mesa_pointer_set_create(ctx); + + foreach_block (block, &ir->block_list) { + foreach_instr (instr, &block->instr_list) { + ctx->current_instr = instr; + validate_instr(ctx, instr); + } + } + + ralloc_free(ctx); +} diff --git a/src/freedreno/ir3/meson.build b/src/freedreno/ir3/meson.build index 44eee947e5c..de56888c22d 100644 --- a/src/freedreno/ir3/meson.build +++ b/src/freedreno/ir3/meson.build @@ -98,6 +98,7 @@ libfreedreno_ir3_files = files( 'ir3_sched.c', 'ir3_shader.c', 'ir3_shader.h', + 'ir3_validate.c', ) libfreedreno_ir3 = static_library(