From 5d3a4e31138f1663b0c37b91d7263bba6025fa73 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 2 Mar 2020 19:30:11 -0500 Subject: [PATCH] pan/bi: Gut old compiler We're making some pretty dramatic design pivots so this early on it'll be easier to start from scratch, I think. Signed-off-by: Alyssa Rosenzweig Part-of: --- src/panfrost/Makefile.sources | 11 +- src/panfrost/bifrost/bifrost.h | 19 + src/panfrost/bifrost/bifrost_compile.c | 1051 ----------------------- src/panfrost/bifrost/bifrost_compile.h | 48 +- src/panfrost/bifrost/bifrost_ops.h | 120 --- src/panfrost/bifrost/bifrost_opts.c | 78 -- src/panfrost/bifrost/bifrost_opts.h | 33 - src/panfrost/bifrost/bifrost_print.c | 156 ---- src/panfrost/bifrost/bifrost_print.h | 35 - src/panfrost/bifrost/bifrost_sched.c | 395 --------- src/panfrost/bifrost/bifrost_sched.h | 29 - src/panfrost/bifrost/cmdline.c | 5 +- src/panfrost/bifrost/compiler_defines.h | 173 ---- src/panfrost/bifrost/disassemble.c | 7 +- src/panfrost/bifrost/meson.build | 4 - 15 files changed, 54 insertions(+), 2110 deletions(-) delete mode 100644 src/panfrost/bifrost/bifrost_compile.c delete mode 100644 src/panfrost/bifrost/bifrost_ops.h delete mode 100644 src/panfrost/bifrost/bifrost_opts.c delete mode 100644 src/panfrost/bifrost/bifrost_opts.h delete mode 100644 src/panfrost/bifrost/bifrost_print.c delete mode 100644 src/panfrost/bifrost/bifrost_print.h delete mode 100644 src/panfrost/bifrost/bifrost_sched.c delete mode 100644 src/panfrost/bifrost/bifrost_sched.h delete mode 100644 src/panfrost/bifrost/compiler_defines.h diff --git a/src/panfrost/Makefile.sources b/src/panfrost/Makefile.sources index ceecb52b1fc..1a912a7f84a 100644 --- a/src/panfrost/Makefile.sources +++ b/src/panfrost/Makefile.sources @@ -1,16 +1,7 @@ bifrost_FILES := \ - bifrost/bifrost_compile.c \ - bifrost/bifrost_compile.h \ bifrost/bifrost.h \ - bifrost/bifrost_ops.h \ - bifrost/bifrost_opts.c \ - bifrost/bifrost_opts.h \ - bifrost/bifrost_print.c \ - bifrost/bifrost_print.h \ - bifrost/bifrost_sched.c \ - bifrost/bifrost_sched.h \ + bifrost/bifrost_compile.h \ bifrost/cmdline.c \ - bifrost/compiler_defines.h \ bifrost/disassemble.c \ bifrost/disassemble.h diff --git a/src/panfrost/bifrost/bifrost.h b/src/panfrost/bifrost/bifrost.h index 439f3a2e960..64a9e8d9a65 100644 --- a/src/panfrost/bifrost/bifrost.h +++ b/src/panfrost/bifrost/bifrost.h @@ -239,4 +239,23 @@ struct bifrost_regs { unsigned ctrl : 4; }; +enum bifrost_branch_cond { + BR_COND_LT = 0, + BR_COND_LE = 1, + BR_COND_GE = 2, + BR_COND_GT = 3, + // Equal vs. not-equal determined by src0/src1 comparison + BR_COND_EQ = 4, + // floating-point comparisons + // Becomes UNE when you flip the arguments + BR_COND_OEQ = 5, + // TODO what happens when you flip the arguments? + BR_COND_OGT = 6, + BR_COND_OLT = 7, +}; + +enum bifrost_branch_code { + BR_ALWAYS = 63, +}; + #endif diff --git a/src/panfrost/bifrost/bifrost_compile.c b/src/panfrost/bifrost/bifrost_compile.c deleted file mode 100644 index 7dc2ec32bc3..00000000000 --- a/src/panfrost/bifrost/bifrost_compile.c +++ /dev/null @@ -1,1051 +0,0 @@ -/* - * Copyright (C) 2019 Ryan Houdek - * - * 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 "compiler/nir/nir_builder.h" -#include "bifrost_compile.h" -#include "bifrost_opts.h" -#include "bifrost_sched.h" -#include "compiler_defines.h" -#include "disassemble.h" -#include "bifrost_print.h" - -#define BI_DEBUG - -static int -glsl_type_size(const struct glsl_type *type, bool bindless) -{ - return glsl_count_attribute_slots(type, false); -} - -static void -optimize_nir(nir_shader *nir) -{ - bool progress; - - NIR_PASS_V(nir, nir_lower_io, nir_var_all, glsl_type_size, 0); - NIR_PASS(progress, nir, nir_lower_regs_to_ssa); - - do { - progress = false; - - NIR_PASS(progress, nir, nir_lower_io, nir_var_all, glsl_type_size, 0); - - NIR_PASS(progress, nir, nir_lower_var_copies); - NIR_PASS(progress, nir, nir_lower_vars_to_ssa); - - NIR_PASS(progress, nir, nir_copy_prop); - NIR_PASS(progress, nir, nir_opt_constant_folding); - - NIR_PASS(progress, nir, nir_lower_vars_to_ssa); - NIR_PASS(progress, nir, nir_lower_alu_to_scalar, NULL, NULL); - NIR_PASS(progress, nir, nir_opt_if, true); - - } while (progress); - - NIR_PASS(progress, nir, nir_copy_prop); - NIR_PASS(progress, nir, nir_opt_dce); -} - -static unsigned -nir_src_index(compiler_context *ctx, nir_src *src) -{ - if (src->is_ssa) - return src->ssa->index; - else - return ctx->func->impl->ssa_alloc + src->reg.reg->index; -} - -static unsigned -nir_dest_index(compiler_context *ctx, nir_dest *dst) -{ - if (dst->is_ssa) - return dst->ssa.index; - else - return ctx->func->impl->ssa_alloc + dst->reg.reg->index; -} - -static unsigned -nir_alu_src_index(compiler_context *ctx, nir_alu_src *src) -{ - return nir_src_index(ctx, &src->src); -} - -struct bifrost_instruction * -mir_alloc_ins(struct bifrost_instruction instr) -{ - struct bifrost_instruction *heap_ins = malloc(sizeof(instr)); - memcpy(heap_ins, &instr, sizeof(instr)); - return heap_ins; -} - -static void -emit_mir_instruction(struct compiler_context *ctx, struct bifrost_instruction instr) -{ - list_addtail(&(mir_alloc_ins(instr))->link, &ctx->current_block->instructions); -} - -static void -bifrost_block_add_successor(bifrost_block *block, bifrost_block *successor) -{ - assert(block->num_successors < ARRAY_SIZE(block->successors)); - block->successors[block->num_successors++] = successor; -} - -static void -emit_load_const(struct compiler_context *ctx, nir_load_const_instr *instr) -{ - nir_ssa_def def = instr->def; - - float *v = ralloc_array(NULL, float, 1); - nir_const_value_to_array(v, instr->value, instr->def.num_components, f32); - _mesa_hash_table_u64_insert(ctx->ssa_constants, def.index + 1, v); -} - -static uint32_t -alloc_mir_temp(struct compiler_context *ctx) -{ - return SSA_TEMP_VALUE(ctx->mir_temp++); -} - -static uint32_t -emit_ld_vary_addr_constant(struct compiler_context *ctx, uint32_t location) -{ - // LD_VAR_ADDR.f32 {R0, T1}, R61, R62, location:1, R12 - // ... - // ST_VAR.v4 T1, R12, R13, R14, R4 - - // R61-R62 is filled with information needed for varying interpolation - // This loads a vec3 with the information that ST_VAR needs to work - - uint32_t mir_temp_location = alloc_mir_temp(ctx); - // This instruction loads a vec3 starting from the initial register - struct bifrost_instruction instr = { - .op = op_ld_var_addr, - .dest_components = 3, - .ssa_args = { - .dest = mir_temp_location, - .src0 = SSA_FIXED_REGISTER(61), - .src1 = SSA_FIXED_REGISTER(62), - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - .literal_args[0] = location, - }; - emit_mir_instruction(ctx, instr); - - return mir_temp_location; -} - -// XXX: Doesn't support duplicated values in the components! -// RA WILL fail! -static void -emit_create_vector(struct compiler_context *ctx, unsigned dest, unsigned num_comps, uint32_t *comps) -{ - assert(num_comps <= 4 && "Can't make a vector larger than 4 components"); - - // This instruction loads a vec3 starting from the initial register - struct bifrost_instruction instr = { - .op = op_create_vector, - .dest_components = num_comps, - .ssa_args = { - .dest = dest, - } - }; - - uint32_t *srcs[4] = { - &instr.ssa_args.src0, - &instr.ssa_args.src1, - &instr.ssa_args.src2, - &instr.ssa_args.src3, - }; - - for (unsigned i = 0; i < 4; ++i) { - if (i < num_comps) - *srcs[i] = comps[i]; - else - *srcs[i] = SSA_INVALID_VALUE; - } - emit_mir_instruction(ctx, instr); -} - -static uint32_t -emit_extract_vector_element(struct compiler_context *ctx, unsigned ssa_vector, unsigned element) -{ - uint32_t mir_temp_location = alloc_mir_temp(ctx); - // This instruction loads a vec3 starting from the initial register - struct bifrost_instruction instr = { - .op = op_extract_element, - .dest_components = 1, - .ssa_args = { - .dest = mir_temp_location, - .src0 = ssa_vector, - .src1 = SSA_INVALID_VALUE, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - .literal_args[0] = element, - }; - emit_mir_instruction(ctx, instr); - - return mir_temp_location; -} -static uint32_t -emit_movi(struct compiler_context *ctx, uint32_t literal) -{ - uint32_t mir_temp_location = alloc_mir_temp(ctx); - // This instruction loads a vec3 starting from the initial register - struct bifrost_instruction instr = { - .op = op_movi, - .dest_components = 1, - .ssa_args = { - .dest = mir_temp_location, - .src0 = SSA_INVALID_VALUE, - .src1 = SSA_INVALID_VALUE, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - .literal_args[0] = literal, - }; - emit_mir_instruction(ctx, instr); - - return mir_temp_location; -} - -static unsigned -nir_alu_src_index_scalar(compiler_context *ctx, nir_alu_instr *nir_instr, unsigned src) -{ - // NIR uses a combination of single channels plus swizzles to determine which component is pulled out of a source - for (unsigned c = 0; c < NIR_MAX_VEC_COMPONENTS; c++) { - if (!nir_alu_instr_channel_used(nir_instr, src, c)) - continue; - // Pull the swizzle from this element that is active and use it as the source - unsigned element = nir_instr->src[src].swizzle[c]; - - // Create an op that extracts an element from a vector - return emit_extract_vector_element(ctx, nir_alu_src_index(ctx, &nir_instr->src[src]), element); - } - assert(0); - return 0; -} - -static void -emit_intrinsic(struct compiler_context *ctx, nir_intrinsic_instr *nir_instr) -{ - nir_const_value *const_offset; - unsigned offset, reg; - - switch (nir_instr->intrinsic) { - case nir_intrinsic_load_ubo: { - nir_const_value *location = nir_src_as_const_value(nir_instr->src[0]); - const_offset = nir_src_as_const_value(nir_instr->src[1]); - assert (location && "no indirect ubo selection"); - assert (const_offset && "no indirect inputs"); - - enum bifrost_ir_ops op; - - // load_ubo , - // ld_ubo , - switch (nir_dest_num_components(nir_instr->dest)) { - case 1: - op = op_ld_ubo_v1; - break; - case 2: - op = op_ld_ubo_v2; - break; - case 3: - op = op_ld_ubo_v3; - break; - case 4: - op = op_ld_ubo_v4; - break; - default: - assert(0); - break; - } - - reg = nir_dest_index(ctx, &nir_instr->dest); - struct bifrost_instruction instr = { - .op = op, - .dest_components = nir_dest_num_components(nir_instr->dest), - .ssa_args = { - .dest = reg, - .src0 = SSA_INVALID_VALUE, - .src1 = SSA_INVALID_VALUE, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - .literal_args[0] = nir_src_as_uint(nir_instr->src[1]), - .literal_args[1] = nir_src_as_uint(nir_instr->src[0]), - }; - - emit_mir_instruction(ctx, instr); - break; - } - case nir_intrinsic_store_ssbo: { - nir_const_value *location = nir_src_as_const_value(nir_instr->src[1]); - const_offset = nir_src_as_const_value(nir_instr->src[2]); - assert (location && "no indirect ubo selection"); - assert (const_offset && "no indirect inputs"); - - // store_ssbo , , - // store_vN , - reg = nir_src_index(ctx, &nir_instr->src[0]); - - enum bifrost_ir_ops op; - switch (nir_src_num_components(nir_instr->src[0])) { - case 1: - op = op_store_v1; - break; - case 2: - op = op_store_v2; - break; - case 3: - op = op_store_v3; - break; - case 4: - op = op_store_v4; - break; - default: - assert(0); - break; - } - - struct bifrost_instruction instr = { - .op = op, - .dest_components = 0, - .ssa_args = { - .dest = SSA_INVALID_VALUE, - .src0 = reg, - .src1 = SSA_INVALID_VALUE, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - .literal_args[0] = nir_src_as_uint(nir_instr->src[2]), - }; - emit_mir_instruction(ctx, instr); - break; - } - case nir_intrinsic_load_uniform: - offset = nir_intrinsic_base(nir_instr); - - if (nir_src_is_const(nir_instr->src[0])) { - offset += nir_src_as_uint(nir_instr->src[0]); - } else { - assert(0 && "Can't handle indirect load_uniform"); - } - - reg = nir_dest_index(ctx, &nir_instr->dest); - - unsigned num_components = nir_dest_num_components(nir_instr->dest); - if (num_components == 1) { - struct bifrost_instruction instr = { - .op = op_mov, - .dest_components = 1, - .ssa_args = { - .dest = reg, - .src0 = SSA_FIXED_UREGISTER(offset), - .src1 = SSA_INVALID_VALUE, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - }; - emit_mir_instruction(ctx, instr); - } else { - uint32_t comps[4]; - - for (unsigned i = 0; i < nir_dest_num_components(nir_instr->dest); ++i) { - uint32_t temp_dest = alloc_mir_temp(ctx); - comps[i] = temp_dest; - struct bifrost_instruction instr = { - .op = op_mov, - .dest_components = 1, - .ssa_args = { - .dest = temp_dest, - .src0 = SSA_FIXED_UREGISTER(offset + (i * 4)), - .src1 = SSA_INVALID_VALUE, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - }; - emit_mir_instruction(ctx, instr); - } - - emit_create_vector(ctx, reg, num_components, comps); - } - break; - - case nir_intrinsic_load_input: { - const_offset = nir_src_as_const_value(nir_instr->src[0]); - assert (const_offset && "no indirect inputs"); - - offset = nir_intrinsic_base(nir_instr) + nir_src_as_uint(nir_instr->src[0]); - - reg = nir_dest_index(ctx, &nir_instr->dest); - - enum bifrost_ir_ops op; - switch (nir_dest_num_components(nir_instr->dest)) { - case 1: - op = op_ld_attr_v1; - break; - case 2: - op = op_ld_attr_v2; - break; - case 3: - op = op_ld_attr_v3; - break; - case 4: - op = op_ld_attr_v4; - break; - default: - assert(0); - break; - } - - struct bifrost_instruction instr = { - .op = op, - .dest_components = nir_dest_num_components(nir_instr->dest), - .ssa_args = { - .dest = reg, - .src0 = offset, - .src1 = SSA_INVALID_VALUE, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - } - }; - - emit_mir_instruction(ctx, instr); - break; - } - case nir_intrinsic_store_output: { - const_offset = nir_src_as_const_value(nir_instr->src[1]); - assert(const_offset && "no indirect outputs"); - - offset = nir_intrinsic_base(nir_instr); - if (ctx->stage == MESA_SHADER_FRAGMENT) { - int comp = nir_intrinsic_component(nir_instr); - offset += comp; - // XXX: Once we support more than colour output then this will need to change - void *entry = _mesa_hash_table_u64_search(ctx->outputs_nir_to_bi, offset + FRAG_RESULT_DATA0 + 1); - - if (!entry) { - printf("WARNING: skipping fragment output\n"); - break; - } - - offset = (uintptr_t) (entry) - 1; - reg = nir_src_index(ctx, &nir_instr->src[0]); - - enum bifrost_ir_ops op; - switch (nir_src_num_components(nir_instr->src[0])) { - case 1: - op = op_store_v1; - break; - case 2: - op = op_store_v2; - break; - case 3: - op = op_store_v3; - break; - case 4: - op = op_store_v4; - break; - default: - assert(0); - break; - } - - // XXX: All offsets aren't vec4 aligned. Will need to adjust this in the future - // XXX: This needs to offset correctly in to memory so the blend step can pick it up - uint32_t movi = emit_movi(ctx, offset * 16); - uint32_t movi2 = emit_movi(ctx, 0); - - uint32_t comps[2] = { - movi, movi2, - }; - uint32_t offset_val = alloc_mir_temp(ctx); - emit_create_vector(ctx, offset_val, 2, comps); - - struct bifrost_instruction instr = { - .op = op, - .dest_components = 0, - .ssa_args = { - .dest = SSA_INVALID_VALUE, - .src0 = offset_val, - .src1 = reg, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - } - }; - emit_mir_instruction(ctx, instr); - } else if (ctx->stage == MESA_SHADER_VERTEX) { - int comp = nir_intrinsic_component(nir_instr); - offset += comp; - void *entry = _mesa_hash_table_u64_search(ctx->varying_nir_to_bi, offset + 2); - - if (!entry) { - printf("WARNING: skipping varying\n"); - break; - } - - offset = (uintptr_t) (entry) - 1; - - reg = nir_src_index(ctx, &nir_instr->src[0]); - // LD_VAR_ADDR.f32 {R0, T1}, R61, R62, location:1, R12 - // ... - // ST_VAR.v4 T1, R12, R13, R14, R4 - - offset = emit_ld_vary_addr_constant(ctx, offset); - enum bifrost_ir_ops op; - switch (nir_src_num_components(nir_instr->src[0])) { - case 1: - op = op_st_vary_v1; - break; - case 2: - op = op_st_vary_v2; - break; - case 3: - op = op_st_vary_v3; - break; - case 4: - op = op_st_vary_v4; - break; - default: - assert(0); - break; - } - - struct bifrost_instruction instr = { - .op = op, - .dest_components = 0, - .ssa_args = { - .dest = SSA_INVALID_VALUE, - .src0 = offset, - .src1 = reg, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - } - }; - emit_mir_instruction(ctx, instr); - } else { - assert(0 && "Unknown store_output stage"); - } - break; - } - default: - printf ("Unhandled intrinsic %s\n", nir_intrinsic_infos[nir_instr->intrinsic].name); - break; - } -} - -#define ALU_CASE(arguments, nir, name) \ - case nir_op_##nir: \ - argument_count = arguments; \ - op = op_##name; \ - break -#define ALU_CASE_MOD(arguments, nir, name, modifiers) \ - case nir_op_##nir: \ - argument_count = arguments; \ - op = op_##name; \ - src_modifiers = modifiers; \ - break - -static void -emit_alu(struct compiler_context *ctx, nir_alu_instr *nir_instr) -{ - unsigned dest = nir_dest_index(ctx, &nir_instr->dest.dest); - unsigned op = ~0U, argument_count; - unsigned src_modifiers = 0; - - switch (nir_instr->op) { - ALU_CASE(2, fmul, fmul_f32); - ALU_CASE(2, fadd, fadd_f32); - ALU_CASE_MOD(2, fsub, fadd_f32, SOURCE_MODIFIER(1, SRC_MOD_NEG)); - ALU_CASE(1, ftrunc, trunc); - ALU_CASE(1, fceil, ceil); - ALU_CASE(1, ffloor, floor); - ALU_CASE(1, fround_even, roundeven); - ALU_CASE(1, frcp, frcp_fast_f32); - ALU_CASE(2, fmax, max_f32); - ALU_CASE(2, fmin, min_f32); - ALU_CASE(2, iadd, add_i32); - ALU_CASE(2, isub, sub_i32); - ALU_CASE(2, imul, mul_i32); - ALU_CASE(2, iand, and_i32); - ALU_CASE(2, ior, or_i32); - ALU_CASE(2, ixor, xor_i32); - ALU_CASE(2, ishl, lshift_i32); - ALU_CASE(2, ushr, rshift_i32); - ALU_CASE(2, ishr, arshift_i32); - case nir_op_ineg: { - unsigned src0 = nir_alu_src_index_scalar(ctx, nir_instr, 0); - printf("ineg 0x%08x\n", src0); - struct bifrost_instruction instr = { - .op = op_sub_i32, - .dest_components = 1, - .ssa_args = { - .dest = dest, - .src0 = SSA_FIXED_CONST_0, - .src1 = src0, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - }; - - emit_mir_instruction(ctx, instr); - return; - - } - case nir_op_vec2: { - uint32_t comps[3] = { - nir_alu_src_index(ctx, &nir_instr->src[0]), - nir_alu_src_index(ctx, &nir_instr->src[1]), - }; - emit_create_vector(ctx, dest, 2, comps); - return; - break; - } - case nir_op_vec3: { - uint32_t comps[3] = { - nir_alu_src_index(ctx, &nir_instr->src[0]), - nir_alu_src_index(ctx, &nir_instr->src[1]), - nir_alu_src_index(ctx, &nir_instr->src[2]), - }; - emit_create_vector(ctx, dest, 3, comps); - return; - break; - } - case nir_op_vec4: { - uint32_t comps[4] = { - nir_alu_src_index(ctx, &nir_instr->src[0]), - nir_alu_src_index(ctx, &nir_instr->src[1]), - nir_alu_src_index(ctx, &nir_instr->src[2]), - nir_alu_src_index(ctx, &nir_instr->src[3]), - }; - emit_create_vector(ctx, dest, 4, comps); - return; - break; - } - case nir_op_fdiv: { - unsigned src0 = nir_alu_src_index_scalar(ctx, nir_instr, 0); - unsigned src1 = nir_alu_src_index_scalar(ctx, nir_instr, 1); - uint32_t mir_temp_location = alloc_mir_temp(ctx); - { - struct bifrost_instruction instr = { - .op = op_frcp_fast_f32, - .dest_components = 1, - .ssa_args = { - .dest = mir_temp_location, - .src0 = src1, - .src1 = SSA_INVALID_VALUE, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - }; - emit_mir_instruction(ctx, instr); - } - - struct bifrost_instruction instr = { - .op = op_fmul_f32, - .dest_components = 1, - .ssa_args = { - .dest = dest, - .src0 = src0, - .src1 = src1, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - .src_modifiers = src_modifiers, - }; - - emit_mir_instruction(ctx, instr); - return; - break; - } - case nir_op_umin: - case nir_op_imin: - case nir_op_umax: - case nir_op_imax: { - unsigned src0 = nir_alu_src_index_scalar(ctx, nir_instr, 0); - unsigned src1 = nir_alu_src_index_scalar(ctx, nir_instr, 1); - struct bifrost_instruction instr = { - .op = op_csel_i32, - .dest_components = 1, - .ssa_args = { - .dest = dest, - .src0 = src0, - .src1 = src1, - .src2 = src0, - .src3 = src1, - }, - .src_modifiers = src_modifiers, - .literal_args[0] = 0, /* XXX: Comparison operator */ - }; - - emit_mir_instruction(ctx, instr); - return; - break; - } - case nir_op_umin3: - case nir_op_imin3: - case nir_op_umax3: - case nir_op_imax3: { - unsigned src0 = nir_alu_src_index_scalar(ctx, nir_instr, 0); - unsigned src1 = nir_alu_src_index_scalar(ctx, nir_instr, 1); - unsigned src2 = nir_alu_src_index_scalar(ctx, nir_instr, 2); - - unsigned op = 0; - if (nir_instr->op == nir_op_umin3) - op = op_umin3_i32; - else if (nir_instr->op == nir_op_imin3) - op = op_imin3_i32; - else if (nir_instr->op == nir_op_umax3) - op = op_umax3_i32; - else if (nir_instr->op == nir_op_imax3) - op = op_imax3_i32; - struct bifrost_instruction instr = { - .op = op, - .dest_components = 1, - .ssa_args = { - .dest = dest, - .src0 = src0, - .src1 = src1, - .src2 = src2, - .src3 = SSA_INVALID_VALUE, - }, - .src_modifiers = src_modifiers, - }; - - emit_mir_instruction(ctx, instr); - - return; - break; - } - case nir_op_ine: { - uint32_t movi = emit_movi(ctx, ~0U); - unsigned src0 = nir_alu_src_index(ctx, &nir_instr->src[0]); - unsigned src1 = nir_alu_src_index(ctx, &nir_instr->src[1]); - struct bifrost_instruction instr = { - .op = op_csel_i32, - .dest_components = 1, - .ssa_args = { - .dest = dest, - .src0 = src0, - .src1 = src1, - .src2 = movi, - .src3 = SSA_FIXED_CONST_0, - }, - .src_modifiers = src_modifiers, - .literal_args[0] = CSEL_IEQ, /* XXX: Comparison operator */ - }; - - emit_mir_instruction(ctx, instr); - return; - break; - } - default: - printf("Unhandled ALU op %s\n", nir_op_infos[nir_instr->op].name); - return; - } - - unsigned src0 = nir_alu_src_index_scalar(ctx, nir_instr, 0); - unsigned src1 = argument_count >= 2 ? nir_alu_src_index_scalar(ctx, nir_instr, 1) : SSA_INVALID_VALUE; - unsigned src2 = argument_count >= 3 ? nir_alu_src_index_scalar(ctx, nir_instr, 2) : SSA_INVALID_VALUE; - unsigned src3 = argument_count >= 4 ? nir_alu_src_index_scalar(ctx, nir_instr, 3) : SSA_INVALID_VALUE; - - struct bifrost_instruction instr = { - .op = op, - .dest_components = 1, - .ssa_args = { - .dest = dest, - .src0 = src0, - .src1 = src1, - .src2 = src2, - .src3 = src3, - }, - .src_modifiers = src_modifiers, - }; - - emit_mir_instruction(ctx, instr); -} - -static void -emit_instr(struct compiler_context *ctx, struct nir_instr *instr) -{ - switch (instr->type) { - case nir_instr_type_load_const: - emit_load_const(ctx, nir_instr_as_load_const(instr)); - break; - case nir_instr_type_intrinsic: - emit_intrinsic(ctx, nir_instr_as_intrinsic(instr)); - break; - case nir_instr_type_alu: - emit_alu(ctx, nir_instr_as_alu(instr)); - break; - case nir_instr_type_tex: - printf("Unhandled NIR inst tex\n"); - break; - case nir_instr_type_jump: - printf("Unhandled NIR inst jump\n"); - break; - case nir_instr_type_ssa_undef: - printf("Unhandled NIR inst ssa_undef\n"); - break; - default: - printf("Unhandled instruction type\n"); - break; - } - -} - -static bifrost_block * -emit_block(struct compiler_context *ctx, nir_block *block) -{ - bifrost_block *this_block = calloc(sizeof(bifrost_block), 1); - list_addtail(&this_block->link, &ctx->blocks); - - ++ctx->block_count; - - /* Add this block to be a successor to the previous block */ - if (ctx->current_block) - bifrost_block_add_successor(ctx->current_block, this_block); - - /* Set up current block */ - list_inithead(&this_block->instructions); - ctx->current_block = this_block; - - nir_foreach_instr(instr, block) { - emit_instr(ctx, instr); - ++ctx->instruction_count; - } - -#ifdef BI_DEBUG - print_mir_block(this_block, false); -#endif - return this_block; -} - -void -emit_if(struct compiler_context *ctx, nir_if *nir_inst); - -static struct bifrost_block * -emit_cf_list(struct compiler_context *ctx, struct exec_list *list) -{ - struct bifrost_block *start_block = NULL; - foreach_list_typed(nir_cf_node, node, node, list) { - switch (node->type) { - case nir_cf_node_block: { - bifrost_block *block = emit_block(ctx, nir_cf_node_as_block(node)); - - if (!start_block) - start_block = block; - - break; - } - - case nir_cf_node_if: - emit_if(ctx, nir_cf_node_as_if(node)); - break; - - default: - case nir_cf_node_loop: - case nir_cf_node_function: - assert(0); - break; - } - } - - return start_block; -} - -void -emit_if(struct compiler_context *ctx, nir_if *nir_inst) -{ - - // XXX: Conditional branch instruction can do a variety of comparisons with the sources - // Merge the source instruction `ine` with our conditional branch - { - uint32_t movi = emit_movi(ctx, ~0U); - struct bifrost_instruction instr = { - .op = op_branch, - .dest_components = 0, - .ssa_args = { - .dest = SSA_INVALID_VALUE, - .src0 = nir_src_index(ctx, &nir_inst->condition), - .src1 = movi, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - .src_modifiers = 0, - .literal_args[0] = BR_COND_EQ, /* XXX: Comparison Arg type */ - .literal_args[1] = 0, /* XXX: Branch target */ - }; - - emit_mir_instruction(ctx, instr); - } - - bifrost_instruction *true_branch = mir_last_instr_in_block(ctx->current_block); - - bifrost_block *true_block = emit_cf_list(ctx, &nir_inst->then_list); - - { - struct bifrost_instruction instr = { - .op = op_branch, - .dest_components = 0, - .ssa_args = { - .dest = SSA_INVALID_VALUE, - .src0 = SSA_INVALID_VALUE, - .src1 = SSA_INVALID_VALUE, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - .src_modifiers = 0, - .literal_args[0] = BR_ALWAYS, /* XXX: ALWAYS */ - .literal_args[1] = 0, /* XXX: Branch target */ - }; - - emit_mir_instruction(ctx, instr); - } - bifrost_instruction *true_exit_branch = mir_last_instr_in_block(ctx->current_block); - - unsigned false_idx = ctx->block_count; - unsigned inst_count = ctx->instruction_count; - - bifrost_block *false_block = emit_cf_list(ctx, &nir_inst->else_list); - - unsigned if_footer_idx = ctx->block_count; - assert(true_block); - assert(false_block); - - - if (ctx->instruction_count == inst_count) { - // If the else branch didn't have anything in it then we can remove the dead jump - mir_remove_instr(true_exit_branch); - } else { - true_exit_branch->literal_args[1] = if_footer_idx; - } - - true_branch->literal_args[1] = false_idx; -} - -int -bifrost_compile_shader_nir(nir_shader *nir, struct bifrost_program *program) -{ - struct compiler_context ictx = { - .nir = nir, - .stage = nir->info.stage, - }; - - struct compiler_context *ctx = &ictx; - - ctx->mir_temp = 0; - - /* Initialize at a global (not block) level hash tables */ - ctx->ssa_constants = _mesa_hash_table_u64_create(NULL); - ctx->hash_to_temp = _mesa_hash_table_u64_create(NULL); - - /* Assign actual uniform location, skipping over samplers */ - ctx->uniform_nir_to_bi = _mesa_hash_table_u64_create(NULL); - - nir_foreach_variable(var, &nir->uniforms) { - if (glsl_get_base_type(var->type) == GLSL_TYPE_SAMPLER) continue; - - for (int col = 0; col < glsl_get_matrix_columns(var->type); ++col) { - int id = ctx->uniform_count++; - _mesa_hash_table_u64_insert(ctx->uniform_nir_to_bi, var->data.driver_location + col + 1, (void *) ((uintptr_t) (id + 1))); - } - } - - if (ctx->stage == MESA_SHADER_VERTEX) { - ctx->varying_nir_to_bi = _mesa_hash_table_u64_create(NULL); - nir_foreach_variable(var, &nir->outputs) { - if (var->data.location < VARYING_SLOT_VAR0) { - if (var->data.location == VARYING_SLOT_POS) - ctx->varying_count++; - _mesa_hash_table_u64_insert(ctx->varying_nir_to_bi, var->data.driver_location + 1, (void *) ((uintptr_t) (1))); - - continue; - } - - for (int col = 0; col < glsl_get_matrix_columns(var->type); ++col) { - for (int comp = 0; comp < 4; ++comp) { - int id = comp + ctx->varying_count++; - _mesa_hash_table_u64_insert(ctx->varying_nir_to_bi, var->data.driver_location + col + comp + 1, (void *) ((uintptr_t) (id + 1))); - } - } - } - - } else if (ctx->stage == MESA_SHADER_FRAGMENT) { - ctx->outputs_nir_to_bi = _mesa_hash_table_u64_create(NULL); - nir_foreach_variable(var, &nir->outputs) { - if (var->data.location >= FRAG_RESULT_DATA0 && var->data.location <= FRAG_RESULT_DATA7) { - int id = ctx->outputs_count++; - printf("Driver location: %d with id %d\n", var->data.location + 1, id); - _mesa_hash_table_u64_insert(ctx->outputs_nir_to_bi, var->data.location + 1, (void *) ((uintptr_t) (id + 1))); - } - } - } - - /* Optimisation passes */ - optimize_nir(nir); - -#ifdef BI_DEBUG - nir_print_shader(nir, stdout); -#endif - - /* Generate machine IR for shader */ - nir_foreach_function(func, nir) { - nir_builder _b; - ctx->b = &_b; - nir_builder_init(ctx->b, func->impl); - - list_inithead(&ctx->blocks); - ctx->block_count = 0; - ctx->func = func; - - emit_cf_list(ctx, &func->impl->body); - - break; // XXX: Once we support multi function shaders then implement - } - - util_dynarray_init(&program->compiled, NULL); - - // MIR pre-RA optimizations - - bool progress = false; - - do { - progress = false; - mir_foreach_block(ctx, block) { - // XXX: Not yet working -// progress |= bifrost_opt_branch_fusion(ctx, block); - } - } while (progress); - - bifrost_schedule_program(ctx); - -#ifdef BI_DEBUG - nir_print_shader(nir, stdout); - disassemble_bifrost(stdout, program->compiled.data, program->compiled.size, false); -#endif - return 0; -} diff --git a/src/panfrost/bifrost/bifrost_compile.h b/src/panfrost/bifrost/bifrost_compile.h index d26c02cfccc..8c8c5e9d014 100644 --- a/src/panfrost/bifrost/bifrost_compile.h +++ b/src/panfrost/bifrost/bifrost_compile.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Ryan Houdek + * Copyright (C) 2018-2019 Alyssa Rosenzweig * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,49 +21,59 @@ * SOFTWARE. */ -#ifndef __bifrost_compile_h__ -#define __bifrost_compile_h__ +#ifndef __BIFROST_PUBLIC_H_ +#define __BIFROST_PUBLIC_H_ #include "compiler/nir/nir.h" #include "util/u_dynarray.h" -struct bifrost_program { +typedef struct { struct util_dynarray compiled; -}; +} bifrost_program; int -bifrost_compile_shader_nir(nir_shader *nir, struct bifrost_program *program); +bifrost_compile_shader_nir(nir_shader *nir, bifrost_program *program); static const nir_shader_compiler_options bifrost_nir_options = { - .fuse_ffma = true, - .lower_flrp16 = true, + .lower_ffma = true, + .lower_sub = true, + .lower_scmp = true, .lower_flrp32 = true, .lower_flrp64 = true, + .lower_ffract = true, .lower_fmod = true, - .lower_bitfield_extract = true, - .lower_bitfield_extract_to_shifts = true, - .lower_bitfield_insert = true, - .lower_bitfield_insert_to_shifts = true, - .lower_bitfield_reverse = true, + .lower_fdiv = true, .lower_idiv = true, .lower_isign = true, - .lower_fsign = true, - .lower_ffract = true, + .lower_fpow = true, + .lower_find_lsb = true, .lower_fdph = true, + + .lower_wpos_pntc = true, + .lower_fsign = true, + + .lower_extract_byte = true, + .lower_extract_word = true, + .lower_rotate = true, + .lower_pack_half_2x16 = true, + .lower_pack_half_2x16_split = true, .lower_pack_unorm_2x16 = true, .lower_pack_snorm_2x16 = true, .lower_pack_unorm_4x8 = true, .lower_pack_snorm_4x8 = true, .lower_unpack_half_2x16 = true, + .lower_unpack_half_2x16_split = true, .lower_unpack_unorm_2x16 = true, .lower_unpack_snorm_2x16 = true, .lower_unpack_unorm_4x8 = true, .lower_unpack_snorm_4x8 = true, - .lower_extract_byte = true, - .lower_extract_word = true, - .lower_all_io_to_temps = true, - .lower_all_io_to_elements = true, + + .lower_doubles_options = nir_lower_dmod, + + .lower_bitfield_extract_to_shifts = true, + .vectorize_io = true, + .use_interpolated_input_intrinsics = true }; #endif diff --git a/src/panfrost/bifrost/bifrost_ops.h b/src/panfrost/bifrost/bifrost_ops.h deleted file mode 100644 index 96aff303a92..00000000000 --- a/src/panfrost/bifrost/bifrost_ops.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2019 Ryan Houdek - * - * 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 __bifrost_ops_h__ -#define __bifrost_ops_h__ - -enum bifrost_ir_ops { - op_fma_f32 = 0x0, - op_fmul_f32, - op_fadd_f32, - op_frcp_fast_f32, - op_max_f32, - op_min_f32, - op_add_i32, - op_sub_i32, - op_imad, - op_mul_i32, - op_or_i32, - op_and_i32, - op_lshift_i32, - op_xor_i32, - op_rshift_i32, - op_arshift_i32, - op_csel_i32, - op_imin3_i32, - op_umin3_i32, - op_imax3_i32, - op_umax3_i32, - - op_branch, - - // unary - op_trunc, - op_ceil, - op_floor, - op_round, - op_roundeven, - - op_mov, - op_movi, - - op_ld_ubo_v1, - op_ld_ubo_v2, - op_ld_ubo_v3, - op_ld_ubo_v4, - - op_ld_attr_v1, - op_ld_attr_v2, - op_ld_attr_v3, - op_ld_attr_v4, - - op_ld_var_addr, - op_st_vary_v1, - op_st_vary_v2, - op_st_vary_v3, - op_st_vary_v4, - - op_store_v1, - op_store_v2, - op_store_v3, - op_store_v4, - - op_create_vector, - op_extract_element, - op_last, -}; - - -enum branch_cond { - BR_COND_LT = 0, - BR_COND_LE = 1, - BR_COND_GE = 2, - BR_COND_GT = 3, - // Equal vs. not-equal determined by src0/src1 comparison - BR_COND_EQ = 4, - // floating-point comparisons - // Becomes UNE when you flip the arguments - BR_COND_OEQ = 5, - // TODO what happens when you flip the arguments? - BR_COND_OGT = 6, - BR_COND_OLT = 7, -}; - -enum branch_code { - BR_ALWAYS = 63, -}; - -enum csel_cond { - CSEL_NEQ_0 = 0, - CSEL_FEQ, - CSEL_FGTR, - CSEL_FGE, - CSEL_IEQ, - CSEL_IGT, - CSEL_IGE, - CSEL_UGT, - CSEL_UGE, -}; - -#endif diff --git a/src/panfrost/bifrost/bifrost_opts.c b/src/panfrost/bifrost/bifrost_opts.c deleted file mode 100644 index 58c9888cc38..00000000000 --- a/src/panfrost/bifrost/bifrost_opts.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2019 Ryan Houdek - * - * 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 "bifrost_opts.h" -#include "compiler_defines.h" - -bool -bifrost_opt_branch_fusion(compiler_context *ctx, bifrost_block *block) -{ - bool progress = false; - mir_foreach_instr_in_block_safe(block, instr) { - if (instr->op != op_branch) continue; - if (instr->literal_args[0] != BR_COND_EQ) continue; - - unsigned src1 = instr->ssa_args.src0; - - // Only work on SSA values - if (src1 >= SSA_FIXED_MINIMUM) continue; - - // Find the source for this conditional branch instruction - // It'll be a CSEL instruction - // If it's comparision is one of the ops that our conditional branch supports - // then we can merge the two - mir_foreach_instr_in_block_from_rev(block, next_instr, instr) { - if (next_instr->op != op_csel_i32) continue; - - if (next_instr->ssa_args.dest == src1) { - // We found the CSEL instruction that is the source here - // Check its condition to make sure it matches what we can fuse - unsigned cond = next_instr->literal_args[0]; - if (cond == CSEL_IEQ) { - // This CSEL is doing an IEQ for our conditional branch doing EQ - // We can just emit a conditional branch that does the comparison - struct bifrost_instruction new_instr = { - .op = op_branch, - .dest_components = 0, - .ssa_args = { - .dest = SSA_INVALID_VALUE, - .src0 = next_instr->ssa_args.src0, - .src1 = next_instr->ssa_args.src1, - .src2 = SSA_INVALID_VALUE, - .src3 = SSA_INVALID_VALUE, - }, - .literal_args[0] = BR_COND_EQ, - .literal_args[1] = instr->literal_args[1], - }; - mir_insert_instr_before(instr, new_instr); - mir_remove_instr(instr); - progress |= true; - break; - } - } - } - } - - return progress; -} - diff --git a/src/panfrost/bifrost/bifrost_opts.h b/src/panfrost/bifrost/bifrost_opts.h deleted file mode 100644 index b152cdd09fd..00000000000 --- a/src/panfrost/bifrost/bifrost_opts.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2019 Ryan Houdek - * - * 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 bifrost_opts_h -#define bifrost_opts_h -#include "compiler_defines.h" - -#include - -bool -bifrost_opt_branch_fusion(compiler_context *ctx, bifrost_block *block); - -#endif /* bifrost_opts_h */ diff --git a/src/panfrost/bifrost/bifrost_print.c b/src/panfrost/bifrost/bifrost_print.c deleted file mode 100644 index c9277760342..00000000000 --- a/src/panfrost/bifrost/bifrost_print.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2019 Ryan Houdek - * - * 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 "compiler_defines.h" -#include "bifrost_print.h" - -const char *ir_names[op_last + 1] = { - "fma.f32", - "fmul.f32", - "fadd.f32", - "frcp_fast.f32", - "max.f32", - "min.f32", - "add.i32", - "sub.i32", - "imad", - "mul.i32", - "or.i32", - "and.i32", - "lshift.i32", - "xor.i32", - "rshift.i32", - "arshift.i32", - "csel.i32", - "imin3.i32", - "umin3.i32", - "imax3.i32", - "umax3.i32", - - "branch", - - // unary - "trunc", - "ceil", - "floor", - "round", - "roundeven", - - "mov", - "movi", - - "ld_ubo.v1", - "ld_ubo.v2", - "ld_ubo.v3", - "ld_ubo.v4", - - "ld_attr.v1", - "ld_attr.v2", - "ld_attr.v3", - "ld_attr.v4", - - "ld_var_addr", - "st_vary.v1", - "st_vary.v2", - "st_vary.v3", - "st_vary.v4", - - "store.v1", - "store.v2", - "store.v3", - "store.v4", - - "create_vector", - "extract_element", - "last", -}; - -void -print_mir_instruction(struct bifrost_instruction *instr, bool post_ra) -{ - printf("\t"); - if (instr->dest_components != 0) { - if (post_ra) { - if (instr->dest_components == 1) { - printf("r%d = ", instr->args.dest); - } else { - printf("r%d..r%d = ", instr->args.dest, instr->args.dest + instr->dest_components - 1); - - } - } else { - printf("%%0x%08x = ", instr->ssa_args.dest); - } - } - - printf("%s ", ir_names[instr->op]); - - if (post_ra) { - uint32_t sources[4] = { - instr->args.src0, - instr->args.src1, - instr->args.src2, - instr->args.src3 - }; - for (unsigned i = 0; i < 4; ++i) { - if (sources[i] == SSA_INVALID_VALUE) break; - bool last = i + 1 == 4 || - sources[i + 1] == SSA_INVALID_VALUE; - - if (sources[i] == SSA_FIXED_CONST_0) { - printf("#0%s", last ? "" : ", "); - } else if (sources[i] >= SSA_FIXED_UREG_MINIMUM) { - printf("u%d%s", SSA_UREG_FROM_FIXED(sources[i]), last ? "" : ", "); - } else { - printf("r%d%s", sources[i], last ? "" : ", "); - } - } - } else { - uint32_t sources[4] = { - instr->ssa_args.src0, - instr->ssa_args.src1, - instr->ssa_args.src2, - instr->ssa_args.src3 - }; - for (unsigned i = 0; i < 4; ++i) { - if (sources[i] == SSA_INVALID_VALUE) break; - bool last = i + 1 == 4 || - sources[i + 1] == SSA_INVALID_VALUE; - - printf("%%0x%08x%s", sources[i], last ? "" : ", "); - } - } - - printf("\n"); -} - -void -print_mir_block(struct bifrost_block *block, bool post_ra) -{ - printf("{\n"); - - mir_foreach_instr_in_block(block, instr) { - print_mir_instruction(instr, post_ra); - } - - printf("}\n"); -} diff --git a/src/panfrost/bifrost/bifrost_print.h b/src/panfrost/bifrost/bifrost_print.h deleted file mode 100644 index 50a561bcb15..00000000000 --- a/src/panfrost/bifrost/bifrost_print.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2019 Ryan Houdek - * - * 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 __bifrost_print_h__ -#define __bifrost_print_h__ - -#include - -struct bifrost_instruction; -struct bifrost_block; - -void print_mir_instruction(struct bifrost_instruction *ins, bool post_ra); -void print_mir_block(struct bifrost_block *block, bool post_ra); - -#endif diff --git a/src/panfrost/bifrost/bifrost_sched.c b/src/panfrost/bifrost/bifrost_sched.c deleted file mode 100644 index 37ae52bac42..00000000000 --- a/src/panfrost/bifrost/bifrost_sched.c +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright (C) 2019 Ryan Houdek - * - * 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 "util/register_allocate.h" -#include "compiler_defines.h" -#include "bifrost_sched.h" -#include "bifrost_compile.h" -#include "bifrost_print.h" - -#define BI_DEBUG -const unsigned max_primary_reg = 64; /* Overestimate because of special regs */ -const unsigned max_vec2_reg = 32; -const unsigned max_vec3_reg = 16; // XXX: Do we need to align vec3 to vec4 boundary? -const unsigned max_vec4_reg = 16; -const unsigned max_registers = 128; /* Sum of classes */ -const unsigned primary_base = 0; -const unsigned vec2_base = 64; -const unsigned vec3_base = 96; /* above base + max_class_reg */ -const unsigned vec4_base = 112; -const unsigned vec4_end = 128; - -static unsigned -find_or_allocate_temp(compiler_context *ctx, unsigned hash) -{ - if (hash >= SSA_FIXED_MINIMUM) - return hash; - - unsigned temp = (uintptr_t) _mesa_hash_table_u64_search(ctx->hash_to_temp, hash + 1); - - if (temp) - return temp - 1; - - /* If no temp is find, allocate one */ - temp = ctx->num_temps++; - ctx->max_hash = MAX2(ctx->max_hash, hash); - - _mesa_hash_table_u64_insert(ctx->hash_to_temp, hash + 1, (void *) ((uintptr_t) temp + 1)); - - return temp; -} - -static bool -is_live_in_instr(bifrost_instruction *instr, unsigned temp) -{ - if (instr->ssa_args.src0 == temp) return true; - if (instr->ssa_args.src1 == temp) return true; - if (instr->ssa_args.src2 == temp) return true; - if (instr->ssa_args.src3 == temp) return true; - - return false; -} - -static bool -is_live_after_instr(compiler_context *ctx, bifrost_block *blk, bifrost_instruction *instr, unsigned temp) -{ - // Scan forward in the block from this location to see if we are still live. - - mir_foreach_instr_in_block_from(blk, ins, mir_next_instr(instr)) { - if (is_live_in_instr(ins, temp)) - return true; - } - - // XXX: Walk all successor blocks and ensure the value isn't used there - - return false; -} - -static uint32_t -ra_select_callback(struct ra_graph *g, BITSET_WORD *regs, void *data) -{ - for (int i = primary_base; i < vec4_end; ++i) { - if (BITSET_TEST(regs, i)) { - return i; - } - } - - assert(0); - return 0; -} - -static uint32_t -ra_get_phys_reg(compiler_context *ctx, struct ra_graph *g, unsigned temp, unsigned max_reg) -{ - if (temp == SSA_INVALID_VALUE || - temp >= SSA_FIXED_UREG_MINIMUM || - temp == SSA_FIXED_CONST_0) - return temp; - - if (temp >= SSA_FIXED_MINIMUM) - return SSA_REG_FROM_FIXED(temp); - - assert(temp < max_reg); - uint32_t r = ra_get_node_reg(g, temp); - if (r >= vec4_base) - return (r - vec4_base) * 4; - else if (r >= vec3_base) - return (r - vec3_base) * 4; - else if (r >= vec2_base) - return (r - vec2_base) * 2; - - return r; -} - -static void -allocate_registers(compiler_context *ctx) -{ - struct ra_regs *regs = ra_alloc_reg_set(NULL, max_registers, true); - - int primary_class = ra_alloc_reg_class(regs); - int vec2_class = ra_alloc_reg_class(regs); - int vec3_class = ra_alloc_reg_class(regs); - int vec4_class = ra_alloc_reg_class(regs); - - // Allocate our register classes and conflicts - { - unsigned reg = 0; - unsigned primary_base = 0; - - // Add all of our primary scalar registers - for (unsigned i = 0; i < max_primary_reg; ++i) { - ra_class_add_reg(regs, primary_class, reg); - reg++; - } - - // Add all of our vec2 class registers - // These alias with the scalar registers - for (unsigned i = 0; i < max_vec2_reg; ++i) { - ra_class_add_reg(regs, vec2_class, reg); - - // Tell RA that this conflicts with primary class registers - // Make sure to tell the RA utility all conflict slots - ra_add_reg_conflict(regs, reg, primary_base + i*2 + 0); - ra_add_reg_conflict(regs, reg, primary_base + i*2 + 1); - - reg++; - } - - // Add all of our vec3 class registers - // These alias with the scalar registers - for (unsigned i = 0; i < max_vec3_reg; ++i) { - ra_class_add_reg(regs, vec3_class, reg); - - // Tell RA that this conflicts with primary class registers - // Make sure to tell the RA utility all conflict slots - // These are aligned to vec4 even though they only conflict with a vec3 wide slot - ra_add_reg_conflict(regs, reg, primary_base + i*4 + 0); - ra_add_reg_conflict(regs, reg, primary_base + i*4 + 1); - ra_add_reg_conflict(regs, reg, primary_base + i*4 + 2); - - // State that this class conflicts with the vec2 class - ra_add_reg_conflict(regs, reg, vec2_base + i*2 + 0); - ra_add_reg_conflict(regs, reg, vec2_base + i*2 + 1); - - reg++; - } - - // Add all of our vec4 class registers - // These alias with the scalar registers - for (unsigned i = 0; i < max_vec4_reg; ++i) { - ra_class_add_reg(regs, vec4_class, reg); - - // Tell RA that this conflicts with primary class registers - // Make sure to tell the RA utility all conflict slots - // These are aligned to vec4 even though they only conflict with a vec3 wide slot - ra_add_reg_conflict(regs, reg, primary_base + i*4 + 0); - ra_add_reg_conflict(regs, reg, primary_base + i*4 + 1); - ra_add_reg_conflict(regs, reg, primary_base + i*4 + 2); - ra_add_reg_conflict(regs, reg, primary_base + i*4 + 3); - - // State that this class conflicts with the vec2 class - ra_add_reg_conflict(regs, reg, vec2_base + i*2 + 0); - ra_add_reg_conflict(regs, reg, vec2_base + i*2 + 1); - - // State that this class conflicts with the vec3 class - // They conflict on the exact same location due to alignments - ra_add_reg_conflict(regs, reg, vec3_base + i); - - reg++; - } - } - - ra_set_finalize(regs, NULL); - mir_foreach_block(ctx, block) { - mir_foreach_instr_in_block(block, instr) { - instr->ssa_args.src0 = find_or_allocate_temp(ctx, instr->ssa_args.src0); - instr->ssa_args.src1 = find_or_allocate_temp(ctx, instr->ssa_args.src1); - instr->ssa_args.src2 = find_or_allocate_temp(ctx, instr->ssa_args.src2); - instr->ssa_args.src3 = find_or_allocate_temp(ctx, instr->ssa_args.src3); - instr->ssa_args.dest = find_or_allocate_temp(ctx, instr->ssa_args.dest); - } - } - - uint32_t nodes = ctx->num_temps; - struct ra_graph *g = ra_alloc_interference_graph(regs, nodes); - - mir_foreach_block(ctx, block) { - mir_foreach_instr_in_block(block, instr) { - if (instr->ssa_args.dest >= SSA_FIXED_MINIMUM) continue; - if (instr->dest_components == 4) - ra_set_node_class(g, instr->ssa_args.dest, vec4_class); - else if (instr->dest_components == 3) - ra_set_node_class(g, instr->ssa_args.dest, vec3_class); - else if (instr->dest_components == 2) - ra_set_node_class(g, instr->ssa_args.dest, vec2_class); - else - ra_set_node_class(g, instr->ssa_args.dest, primary_class); - } - } - - uint32_t *live_start = malloc(nodes * sizeof(uint32_t)); - uint32_t *live_end = malloc(nodes * sizeof(uint32_t)); - - memset(live_start, 0xFF, nodes * sizeof(uint32_t)); - memset(live_end, 0xFF, nodes * sizeof(uint32_t)); - - uint32_t location = 0; - mir_foreach_block(ctx, block) { - mir_foreach_instr_in_block(block, instr) { - if (instr->ssa_args.dest < SSA_FIXED_MINIMUM) { - // If the destination isn't yet live before this point - // then this is the point it becomes live since we wrote to it - if (live_start[instr->ssa_args.dest] == ~0U) { - live_start[instr->ssa_args.dest] = location; - } - } - - uint32_t sources[4] = { - instr->ssa_args.src0, - instr->ssa_args.src1, - instr->ssa_args.src2, - instr->ssa_args.src3, - }; - - for (unsigned i = 0; i < 4; ++i) { - if (sources[i] >= SSA_FIXED_MINIMUM) - continue; - - // If the source is no longer live after this instruction then we can end its liveness - if (!is_live_after_instr(ctx, block, instr, sources[i])) { - live_end[sources[i]] = location; - } - } - ++location; - } - } - - // Spin through the nodes quick and ensure they are all killed by the end of the program - for (unsigned i = 0; i < nodes; ++i) { - if (live_end[i] == ~0U) - live_end[i] = location; - } - - for (int i = 0; i < nodes; ++i) { - for (int j = i + 1; j < nodes; ++j) { - if (!(live_start[i] >= live_end[j] || live_start[j] >= live_end[i])) { - ra_add_node_interference(g, i, j); - } - } - } - - ra_set_select_reg_callback(g, ra_select_callback, NULL); - - if (!ra_allocate(g)) { - assert(0); - } - - free(live_start); - free(live_end); - - mir_foreach_block(ctx, block) { - mir_foreach_instr_in_block(block, instr) { - instr->args.src0 = ra_get_phys_reg(ctx, g, instr->ssa_args.src0, nodes); - instr->args.src1 = ra_get_phys_reg(ctx, g, instr->ssa_args.src1, nodes); - instr->args.src2 = ra_get_phys_reg(ctx, g, instr->ssa_args.src2, nodes); - instr->args.src3 = ra_get_phys_reg(ctx, g, instr->ssa_args.src3, nodes); - instr->args.dest = ra_get_phys_reg(ctx, g, instr->ssa_args.dest, nodes); - } - } -} - -static void -bundle_block(compiler_context *ctx, bifrost_block *block) -{ -} - -static void -remove_create_vectors(compiler_context *ctx, bifrost_block *block) -{ - mir_foreach_instr_in_block_safe(block, instr) { - if (instr->op != op_create_vector) continue; - - uint32_t vector_ssa_sources[4] = { - instr->ssa_args.src0, - instr->ssa_args.src1, - instr->ssa_args.src2, - instr->ssa_args.src3, - }; - - mir_foreach_instr_in_block_from_rev(block, next_instr, instr) { - // Walk our block backwards and find the creators of this vector creation instruction - for (unsigned i = 0; i < instr->dest_components; ++i) { - // If this instruction is ther one that writes this register then forward it to the real register - if (vector_ssa_sources[i] == next_instr->ssa_args.dest) { - next_instr->ssa_args.dest = vector_ssa_sources[i]; - // Source instruction destination is a vector register of size dest_components - // So dest + i gets the components of it - next_instr->args.dest = instr->args.dest + i; - } - } - } - - // Remove the instruction now that we have copied over all the sources - mir_remove_instr(instr); - } -} - -static void -remove_extract_elements(compiler_context *ctx, bifrost_block *block) -{ - mir_foreach_instr_in_block_safe(block, instr) { - if (instr->op != op_extract_element) continue; - - mir_foreach_instr_in_block_from(block, next_instr, instr) { - // Walk our block forward to replace uses of this register with a real register - // src0 = vector - // src1 = index in to vector - uint32_t vector_ssa_sources[4] = { - next_instr->ssa_args.src0, - next_instr->ssa_args.src1, - next_instr->ssa_args.src2, - next_instr->ssa_args.src3, - }; - uint32_t *vector_sources[4] = { - &next_instr->args.src0, - &next_instr->args.src1, - &next_instr->args.src2, - &next_instr->args.src3, - }; - - for (unsigned i = 0; i < 4; ++i) { - if (vector_ssa_sources[i] == instr->ssa_args.dest) { - // This source uses this vector extraction - // Replace its usage with the real register - // src0 is a vector register and src1 is the constant element of the vector - *vector_sources[i] = instr->args.src0 + instr->literal_args[0]; - } - } - - } - - // Remove the instruction now that we have copied over all the sources - mir_remove_instr(instr); - } -} - - -void bifrost_schedule_program(compiler_context *ctx) -{ - // XXX: we should move instructions together before RA that can feed in to each other and be scheduled in the same clause - allocate_registers(ctx); - - mir_foreach_block(ctx, block) { - remove_create_vectors(ctx, block); - remove_extract_elements(ctx, block); - } - - mir_foreach_block(ctx, block) { -#ifdef BI_DEBUG - print_mir_block(block, true); -#endif - - bundle_block(ctx, block); - } -} - diff --git a/src/panfrost/bifrost/bifrost_sched.h b/src/panfrost/bifrost/bifrost_sched.h deleted file mode 100644 index 7edd95a9dfb..00000000000 --- a/src/panfrost/bifrost/bifrost_sched.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2019 Ryan Houdek - * - * 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 bifrost_ra_h -#define bifrost_ra_h -#include "compiler_defines.h" - -void bifrost_schedule_program(compiler_context *ctx); - -#endif /* bifrost_ra_h */ diff --git a/src/panfrost/bifrost/cmdline.c b/src/panfrost/bifrost/cmdline.c index 2c0d1a23553..f9094d511ea 100644 --- a/src/panfrost/bifrost/cmdline.c +++ b/src/panfrost/bifrost/cmdline.c @@ -29,7 +29,6 @@ #include "compiler/glsl/gl_nir.h" #include "compiler/nir_types.h" #include "util/u_dynarray.h" - #include "bifrost_compile.h" static void @@ -52,7 +51,7 @@ compile_shader(char **argv) prog = standalone_compile_shader(&options, 2, argv, &local_ctx); prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program->info.stage = MESA_SHADER_FRAGMENT; - struct bifrost_program compiled; + bifrost_program compiled; for (unsigned i = 0; i < 2; ++i) { nir[i] = glsl_to_nir(&local_ctx, prog, shader_types[i], &bifrost_nir_options); NIR_PASS_V(nir[i], nir_lower_global_vars_to_local); @@ -66,7 +65,7 @@ compile_shader(char **argv) NIR_PASS_V(nir[i], gl_nir_lower_buffers, prog); NIR_PASS_V(nir[i], nir_opt_constant_folding); - bifrost_compile_shader_nir(nir[i], &compiled); + //bifrost_compile_shader_nir(nir[i], &compiled); } } diff --git a/src/panfrost/bifrost/compiler_defines.h b/src/panfrost/bifrost/compiler_defines.h deleted file mode 100644 index a853b2d0e60..00000000000 --- a/src/panfrost/bifrost/compiler_defines.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2019 Ryan Houdek - * - * 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 __compiler_defines_h__ -#define __compiler_defines_h__ -#include "bifrost.h" -#include "bifrost_compile.h" -#include "bifrost_ops.h" - -struct nir_builder; - -typedef struct ssa_args { - uint32_t dest; - uint32_t src0, src1, src2, src3; -} ssa_args; - -/** - * @brief Singular unpacked instruction that lives outside of the clause bundle - */ -typedef struct bifrost_instruction { - // Must be first - struct list_head link; - - /** - * @brief Pre-RA arguments - */ - struct ssa_args ssa_args; - uint32_t literal_args[4]; - uint32_t src_modifiers; - unsigned op; - - - /** - * @brief Post-RA arguments - */ - struct ssa_args args; - - /** - * @brief The number of components that the destination takes up - * - * This allows the RA to understand when it needs to allocate registers from different classes - */ - unsigned dest_components; - -} bifrost_instruction; - -typedef struct bifrost_clause { - struct bifrost_header header; - - /* List of bifrost_instructions emitted for the current clause */ - struct list_head instructions; - -} bifrost_clause; - -typedef struct bifrost_block { - /* Link to next block. Must be first for mir_get_block */ - struct list_head link; - - /* List of bifrost_instructions emitted for the current block */ - struct list_head instructions; - - /* List of bifrost clauses to be emitted for the current block*/ - struct util_dynarray clauses; - - /* Maximum number of successors is 2 */ - struct bifrost_block *successors[2]; - uint32_t num_successors; - -} bifrost_block; - -typedef struct compiler_context { - nir_shader *nir; - gl_shader_stage stage; - - /* Current NIR function */ - nir_function *func; - struct nir_builder *b; - - /* Unordered list of bifrost_blocks */ - uint32_t block_count; - struct list_head blocks; - - /* The current block we are operating on */ - struct bifrost_block *current_block; - - struct hash_table_u64 *ssa_constants; - - /* Uniform IDs */ - struct hash_table_u64 *uniform_nir_to_bi; - uint32_t uniform_count; - - struct hash_table_u64 *varying_nir_to_bi; - uint32_t varying_count; - - struct hash_table_u64 *outputs_nir_to_bi; - uint32_t outputs_count; - - /* Count of instructions emitted from NIR overall, across all blocks */ - uint32_t instruction_count; - - uint32_t mir_temp; - - struct hash_table_u64 *hash_to_temp; - uint32_t num_temps; - - uint32_t max_hash; - -} compiler_context; - -#define mir_foreach_block(ctx, v) list_for_each_entry(struct bifrost_block, v, &ctx->blocks, link) -#define mir_foreach_block_from(ctx, from, v) list_for_each_entry_from(struct bifrost_block, v, from, &ctx->blocks, link) - -#define mir_last_block(ctx) list_last_entry(&ctx->blocks, struct bifrost_block, link) - -#define mir_foreach_instr(ctx, v) list_for_each_entry(struct bifrost_instruction, v, &ctx->current_block->instructions, link) -#define mir_foreach_instr_in_block(block, v) list_for_each_entry(struct bifrost_instruction, v, &block->instructions, link) -#define mir_foreach_instr_in_block_from(block, v, from) list_for_each_entry_from(struct bifrost_instruction, v, from, &block->instructions, link) -#define mir_foreach_instr_in_block_safe(block, v) list_for_each_entry_safe(struct bifrost_instruction, v, &block->instructions, link) -#define mir_last_instr_in_block(block) list_last_entry(&block->instructions, struct bifrost_instruction, link) -#define mir_foreach_instr_in_block_from_rev(block, v, from) list_for_each_entry_from_rev(struct bifrost_instruction, v, from, &block->instructions, link) - -#define mir_next_instr(from) list_first_entry(&(from->link), struct bifrost_instruction, link) -#define mir_remove_instr(instr) list_del(&instr->link) - -#define mir_insert_instr_before(before, ins) list_addtail(&(mir_alloc_ins(ins))->link, &before->link) - -#define SSA_INVALID_VALUE ~0U -#define SSA_TEMP_SHIFT 24 -#define SSA_FIXED_REGISTER_SHIFT 25 - -#define SSA_FIXED_REGISTER(x) ((1U << SSA_FIXED_REGISTER_SHIFT) + (x)) -#define SSA_REG_FROM_FIXED(x) ((x) & ~(1U << SSA_FIXED_REGISTER_SHIFT)) - -#define SSA_FIXED_MINIMUM SSA_FIXED_REGISTER(0) -#define SSA_FIXED_UREG_MINIMUM SSA_FIXED_REGISTER(64) -#define SSA_FIXED_CONST_0 SSA_FIXED_REGISTER(256 + 64) - -#define SSA_FIXED_UREGISTER(x) (SSA_FIXED_REGISTER(x + 64)) -#define SSA_UREG_FROM_FIXED(x) (SSA_REG_FROM_FIXED(x) - 64) - -#define SSA_TEMP_VALUE(x) ((1U << SSA_TEMP_SHIFT) + (x)) -#define SSA_TEMP_FROM_VALUE(x) (((x) & ~(1U << SSA_TEMP_SHIFT))) -#define MIR_TEMP_MINIMUM SSA_TEMP_VALUE(0) - -#define SRC_MOD_ABS 1 -#define SRC_MOD_NEG 2 -#define MOD_SIZE 2 -#define SOURCE_MODIFIER(src, mod) (mod << (src * MOD_SIZE)) - -struct bifrost_instruction * -mir_alloc_ins(struct bifrost_instruction instr); - -#endif diff --git a/src/panfrost/bifrost/disassemble.c b/src/panfrost/bifrost/disassemble.c index 9e50f6ae071..975d88bf383 100644 --- a/src/panfrost/bifrost/disassemble.c +++ b/src/panfrost/bifrost/disassemble.c @@ -31,7 +31,6 @@ #include #include "bifrost.h" -#include "bifrost_ops.h" #include "disassemble.h" #include "util/macros.h" @@ -1339,11 +1338,11 @@ static void dump_add(FILE *fp, uint64_t word, struct bifrost_regs regs, } fprintf(fp, ".v%d", ((ADD.op >> 5) & 0x3) + 1); } else if (info.src_type == ADD_BRANCH) { - enum branch_code branchCode = (enum branch_code) ((ADD.op >> 6) & 0x3f); + enum bifrost_branch_code branchCode = (enum bifrost_branch_code) ((ADD.op >> 6) & 0x3f); if (branchCode == BR_ALWAYS) { // unconditional branch } else { - enum branch_cond cond = (enum branch_cond) ((ADD.op >> 6) & 0x7); + enum bifrost_branch_cond cond = (enum bifrost_branch_cond) ((ADD.op >> 6) & 0x7); enum branch_bit_size size = (enum branch_bit_size) ((ADD.op >> 9) & 0x7); bool portSwapped = (ADD.op & 0x7) < ADD.src0; // See the comment in branch_bit_size @@ -1814,7 +1813,7 @@ static void dump_add(FILE *fp, uint64_t word, struct bifrost_regs regs, dump_16swizzle(fp, (ADD.op >> 8) & 0x3); break; case ADD_BRANCH: { - enum branch_code code = (enum branch_code) ((ADD.op >> 6) & 0x3f); + enum bifrost_branch_code code = (enum bifrost_branch_code) ((ADD.op >> 6) & 0x3f); enum branch_bit_size size = (enum branch_bit_size) ((ADD.op >> 9) & 0x7); if (code != BR_ALWAYS) { dump_src(fp, ADD.src0, regs, consts, false); diff --git a/src/panfrost/bifrost/meson.build b/src/panfrost/bifrost/meson.build index b49170a35ff..35c9c9397bc 100644 --- a/src/panfrost/bifrost/meson.build +++ b/src/panfrost/bifrost/meson.build @@ -20,10 +20,6 @@ # SOFTWARE. libpanfrost_bifrost_files = files( - 'bifrost_compile.c', - 'bifrost_opts.c', - 'bifrost_sched.c', - 'bifrost_print.c', 'disassemble.c', ) -- 2.30.2