diff --git a/src/asahi/compiler/agx_builder.h.py b/src/asahi/compiler/agx_builder.h.py index 79f7bbd77a8..79c2cc18eaf 100644 --- a/src/asahi/compiler/agx_builder.h.py +++ b/src/asahi/compiler/agx_builder.h.py @@ -27,10 +27,19 @@ template = """/* #include "agx_compiler.h" static inline agx_instr * -agx_alloc_instr(agx_builder *b, enum agx_opcode op) +agx_alloc_instr(agx_builder *b, enum agx_opcode op, uint8_t nr_dests, uint8_t nr_srcs) { - agx_instr *I = rzalloc(b->shader, agx_instr); + size_t size = sizeof(agx_instr); + size += sizeof(agx_index) * nr_dests; + size += sizeof(agx_index) * nr_srcs; + + agx_instr *I = (agx_instr *) rzalloc_size(b->shader, size); + I->dest = (agx_index *) (I + 1); + I->src = I->dest + nr_dests; + I->op = op; + I->nr_dests = nr_dests; + I->nr_srcs = nr_srcs; return I; } @@ -41,11 +50,17 @@ agx_alloc_instr(agx_builder *b, enum agx_opcode op) srcs = op.srcs imms = op.imms suffix = "_to" if dests > 0 else "" + nr_dests = "nr_dests" if op.variable_dests else str(dests) + nr_srcs = "nr_srcs" if op.variable_srcs else str(srcs) %> static inline agx_instr * agx_${opcode}${suffix}(agx_builder *b +% if op.variable_dests: + , unsigned nr_dests +% endif + % for dest in range(dests): , agx_index dst${dest} % endfor @@ -63,23 +78,15 @@ agx_${opcode}${suffix}(agx_builder *b % endfor ) { - agx_instr *I = agx_alloc_instr(b, AGX_OPCODE_${opcode.upper()}); + agx_instr *I = agx_alloc_instr(b, AGX_OPCODE_${opcode.upper()}, ${nr_dests}, ${nr_srcs}); % for dest in range(dests): I->dest[${dest}] = dst${dest}; % endfor -% if op.variable_srcs: - I->src = ralloc_array(I, agx_index, nr_srcs); - I->nr_srcs = nr_srcs; -% elif srcs > 0: - I->src = ralloc_array(I, agx_index, ${srcs}); - I->nr_srcs = ${srcs}; - % for src in range(srcs): I->src[${src}] = src${src}; % endfor -% endif % for imm in imms: I->${imm.name} = ${imm.name}; @@ -89,7 +96,7 @@ agx_${opcode}${suffix}(agx_builder *b return I; } -% if dests == 1 and not op.variable_srcs: +% if dests == 1 and not op.variable_srcs and not op.variable_dests: static inline agx_index agx_${opcode}(agx_builder *b diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index 393fdeb1685..76fcb30d1f5 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -1207,7 +1207,8 @@ agx_emit_jump(agx_builder *b, nir_jump_instr *instr) static void agx_emit_phi(agx_builder *b, nir_phi_instr *instr) { - agx_instr *I = agx_phi_to(b, agx_dest_index(&instr->dest)); + agx_instr *I = agx_phi_to(b, agx_dest_index(&instr->dest), + exec_list_length(&instr->srcs)); /* Deferred */ I->phi = instr; @@ -1230,9 +1231,6 @@ agx_emit_phi_deferred(agx_context *ctx, agx_block *block, agx_instr *I) /* Guaranteed by lower_phis_to_scalar */ assert(phi->dest.ssa.num_components == 1); - I->nr_srcs = exec_list_length(&phi->srcs); - I->src = rzalloc_array(I, agx_index, I->nr_srcs); - nir_foreach_phi_src(src, phi) { agx_block *pred = agx_from_nir_block(ctx, src->pred); unsigned i = agx_predecessor_index(block, pred); diff --git a/src/asahi/compiler/agx_compiler.h b/src/asahi/compiler/agx_compiler.h index 1078314a0e7..a1486169c55 100644 --- a/src/asahi/compiler/agx_compiler.h +++ b/src/asahi/compiler/agx_compiler.h @@ -288,12 +288,13 @@ typedef struct { nir_phi_instr *phi; }; + /* Data flow */ + agx_index *dest; + enum agx_opcode op; - /* Data flow */ - agx_index dest[AGX_MAX_DESTS]; - - unsigned nr_srcs; + uint8_t nr_dests; + uint8_t nr_srcs; union { uint32_t imm; @@ -534,7 +535,7 @@ agx_vec_for_intr(agx_context *ctx, nir_intrinsic_instr *instr) for (unsigned v = 0; v < ins->nr_srcs; ++v) #define agx_foreach_dest(ins, v) \ - for (unsigned v = 0; v < ARRAY_SIZE(ins->dest); ++v) + for (unsigned v = 0; v < ins->nr_dests; ++v) /* Phis only come at the start so we stop as soon as we hit a non-phi */ #define agx_foreach_phi_in_block(block, v) \ diff --git a/src/asahi/compiler/agx_lower_pseudo.c b/src/asahi/compiler/agx_lower_pseudo.c index 2752aa64e46..0efe0f5c7f1 100644 --- a/src/asahi/compiler/agx_lower_pseudo.c +++ b/src/asahi/compiler/agx_lower_pseudo.c @@ -25,40 +25,38 @@ #include "agx_builder.h" /* Lower pseudo instructions created during optimization. */ - -static void -agx_lower_to_unary_bitop(agx_instr *I, enum agx_bitop_table table) +static agx_instr * +lower(agx_builder *b, agx_instr *I) { - I->op = AGX_OPCODE_BITOP; - I->truth_table = table; + switch (I->op) { - /* Allocate extra source */ - I->src = reralloc_array_size(I, I->src, sizeof(agx_index), I->nr_srcs++); - I->src[1] = agx_zero(); -} + /* Various instructions are implemented as bitwise truth tables */ + case AGX_OPCODE_MOV: + return agx_bitop_to(b, I->dest[0], I->src[0], agx_zero(), AGX_BITOP_MOV); -static void -agx_lower_to_binary_bitop(agx_instr *I, enum agx_bitop_table table) -{ - I->op = AGX_OPCODE_BITOP; - I->truth_table = table; + case AGX_OPCODE_NOT: + return agx_bitop_to(b, I->dest[0], I->src[0], agx_zero(), AGX_BITOP_NOT); + + case AGX_OPCODE_AND: + return agx_bitop_to(b, I->dest[0], I->src[0], I->src[1], AGX_BITOP_AND); + + case AGX_OPCODE_XOR: + return agx_bitop_to(b, I->dest[0], I->src[0], I->src[1], AGX_BITOP_XOR); + + case AGX_OPCODE_OR: + return agx_bitop_to(b, I->dest[0], I->src[0], I->src[1], AGX_BITOP_OR); + + default: return NULL; + } } void agx_lower_pseudo(agx_context *ctx) { - agx_foreach_instr_global(ctx, I) { - switch (I->op) { + agx_foreach_instr_global_safe(ctx, I) { + agx_builder b = agx_init_builder(ctx, agx_before_instr(I)); - /* Various instructions are implemented as bitwise truth tables */ - case AGX_OPCODE_MOV: agx_lower_to_unary_bitop(I, AGX_BITOP_MOV); break; - case AGX_OPCODE_NOT: agx_lower_to_unary_bitop(I, AGX_BITOP_NOT); break; - case AGX_OPCODE_AND: agx_lower_to_binary_bitop(I, AGX_BITOP_AND); break; - case AGX_OPCODE_XOR: agx_lower_to_binary_bitop(I, AGX_BITOP_XOR); break; - case AGX_OPCODE_OR: agx_lower_to_binary_bitop(I, AGX_BITOP_OR); break; - - default: - break; - } + if (lower(&b, I)) + agx_remove_instruction(I); } } diff --git a/src/asahi/compiler/agx_opcodes.py b/src/asahi/compiler/agx_opcodes.py index e7725537eed..9d73613b4c9 100644 --- a/src/asahi/compiler/agx_opcodes.py +++ b/src/asahi/compiler/agx_opcodes.py @@ -267,9 +267,6 @@ op("logical_end", _, dests = 0, srcs = 0, can_eliminate = False) op("combine", _, srcs = VARIABLE) op("split", _, srcs = 1, dests = 4) - -# Phis are special-cased in the IR as they (uniquely) can take an unbounded -# number of source. -op("phi", _, srcs = 0) +op("phi", _, srcs = VARIABLE) op("unit_test", _, dests = 0, srcs = 1, can_eliminate = False) diff --git a/src/asahi/compiler/test/agx_test.h b/src/asahi/compiler/test/agx_test.h index ddb27b1361a..08b817757ee 100644 --- a/src/asahi/compiler/test/agx_test.h +++ b/src/asahi/compiler/test/agx_test.h @@ -58,7 +58,7 @@ agx_test_builder(void *memctx) static inline bool agx_instr_equal(agx_instr *A, agx_instr *B) { - unsigned pointers = sizeof(struct list_head) + sizeof(agx_index *); + unsigned pointers = sizeof(struct list_head) + sizeof(agx_index *) * 2; if (A->nr_srcs != B->nr_srcs) return false; @@ -66,6 +66,12 @@ agx_instr_equal(agx_instr *A, agx_instr *B) if (memcmp(A->src, B->src, A->nr_srcs * sizeof(agx_index))) return false; + if (A->nr_dests != B->nr_dests) + return false; + + if (memcmp(A->dest, B->dest, A->nr_dests * sizeof(agx_index))) + return false; + return memcmp((uint8_t *) A + pointers, (uint8_t *) B + pointers, sizeof(agx_instr) - pointers) == 0;