From c215895eaed33caed0451bb0acfc2e0796e87424 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Sun, 11 Apr 2021 16:01:47 -0400 Subject: [PATCH] agx: Add a trivial register allocator Signed-off-by: Alyssa Rosenzweig Acked-by: Jason Ekstrand Acked-by: Bas Nieuwenhuizen Part-of: --- src/asahi/compiler/agx_compile.c | 5 + src/asahi/compiler/agx_compiler.h | 1 + src/asahi/compiler/agx_register_allocate.c | 103 +++++++++++++++++++++ src/asahi/compiler/meson.build | 1 + 4 files changed, 110 insertions(+) create mode 100644 src/asahi/compiler/agx_register_allocate.c diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index 76cc4b96d73d2..c720024835f29 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -500,6 +500,11 @@ agx_compile_shader_nir(nir_shader *nir, agx_foreach_block(ctx, block) block->name = block_source_count++; + if (agx_debug & AGX_DBG_SHADERS && !skip_internal) + agx_print_shader(ctx, stdout); + + agx_ra(ctx); + if (agx_debug & AGX_DBG_SHADERS && !skip_internal) agx_print_shader(ctx, stdout); diff --git a/src/asahi/compiler/agx_compiler.h b/src/asahi/compiler/agx_compiler.h index a72ca17260b25..0dc204962cf35 100644 --- a/src/asahi/compiler/agx_compiler.h +++ b/src/asahi/compiler/agx_compiler.h @@ -547,5 +547,6 @@ agx_builder_insert(agx_cursor *cursor, agx_instr *I) void agx_print_instr(agx_instr *I, FILE *fp); void agx_print_block(agx_block *block, FILE *fp); void agx_print_shader(agx_context *ctx, FILE *fp); +void agx_ra(agx_context *ctx); #endif diff --git a/src/asahi/compiler/agx_register_allocate.c b/src/asahi/compiler/agx_register_allocate.c new file mode 100644 index 0000000000000..5e4760328d904 --- /dev/null +++ b/src/asahi/compiler/agx_register_allocate.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2021 Alyssa Rosenzweig + * + * 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 "agx_compiler.h" +#include "agx_builder.h" + +/* Trivial register allocator that never frees anything. + * + * TODO: Write a real register allocator. + * TODO: Handle phi nodes. + */ + +void +agx_ra(agx_context *ctx) +{ + unsigned *alloc = calloc(ctx->alloc, sizeof(unsigned)); + unsigned usage = 6*2; + + agx_foreach_instr_global_safe(ctx, ins) { + /* Lower away RA pseudo-instructions */ + if (ins->op == AGX_OPCODE_P_COMBINE) { + /* TODO: Optimize out the moves! */ + unsigned components = 0; + + for (unsigned i = 0; i < 4; ++i) { + if (!agx_is_null(ins->src[i])) + components = i + 1; + } + + unsigned size = ins->dest[0].size == AGX_SIZE_32 ? 2 : 1; + if (size == 2 && usage & 1) usage++; + unsigned base = usage; + assert(ins->dest[0].type == AGX_INDEX_NORMAL); + alloc[ins->dest[0].value] = base; + usage += (components * size); + + /* Move the sources */ + agx_builder b = agx_init_builder(ctx, agx_after_instr(ins)); + + for (unsigned i = 0; i < 4; ++i) { + if (agx_is_null(ins->src[i])) continue; + assert(ins->src[0].type == AGX_INDEX_NORMAL); + agx_mov_to(&b, agx_register(base + (i * size), ins->dest[0].size), + agx_register(alloc[ins->src[i].value], ins->src[0].size)); + } + + /* We've lowered away, delete the old */ + agx_remove_instruction(ins); + continue; + } else if (ins->op == AGX_OPCODE_P_EXTRACT) { + assert(ins->dest[0].type == AGX_INDEX_NORMAL); + assert(ins->src[0].type == AGX_INDEX_NORMAL); + assert(ins->dest[0].size == ins->src[0].size); + + unsigned size = ins->dest[0].size == AGX_SIZE_32 ? 2 : 1; + alloc[ins->dest[0].value] = alloc[ins->src[0].value] + (size * ins->imm); + agx_remove_instruction(ins); + continue; + } + + agx_foreach_src(ins, s) { + if (ins->src[s].type == AGX_INDEX_NORMAL) { + unsigned v = alloc[ins->src[s].value]; + ins->src[s] = agx_replace_index(ins->src[s], agx_register(v, ins->src[s].size)); + } + } + + agx_foreach_dest(ins, d) { + if (ins->dest[d].type == AGX_INDEX_NORMAL) { + unsigned size = ins->dest[d].size == AGX_SIZE_32 ? 2 : 1; + if (size == 2 && usage & 1) usage++; + unsigned v = usage; + unsigned comps = (ins->op == AGX_OPCODE_LD_VARY || ins->op == AGX_OPCODE_DEVICE_LOAD || ins->op == AGX_OPCODE_TEXTURE_SAMPLE) ? 4 : 1; // todo systematic + usage += comps * size; + alloc[ins->dest[d].value] = v; + ins->dest[d] = agx_replace_index(ins->dest[d], agx_register(v, ins->dest[d].size)); + } + } + } + + assert(usage < 256 && "dummy RA"); + free(alloc); +} diff --git a/src/asahi/compiler/meson.build b/src/asahi/compiler/meson.build index ed66fc0924a8b..3e5471b562262 100644 --- a/src/asahi/compiler/meson.build +++ b/src/asahi/compiler/meson.build @@ -22,6 +22,7 @@ libasahi_agx_files = files( 'agx_compile.c', 'agx_print.c', + 'agx_register_allocate.c', ) agx_opcodes_h = custom_target(