diff --git a/src/asahi/compiler/agx_builder.h.py b/src/asahi/compiler/agx_builder.h.py index 6638d408c4e..a6b45e04623 100644 --- a/src/asahi/compiler/agx_builder.h.py +++ b/src/asahi/compiler/agx_builder.h.py @@ -7,6 +7,7 @@ template = """/* #define _AGX_BUILDER_ #include "agx_compiler.h" +#include "util/lut.h" static inline agx_instr * agx_alloc_instr(agx_builder *b, enum agx_opcode op, uint8_t nr_dests, uint8_t nr_srcs) @@ -113,27 +114,11 @@ agx_${opcode}(agx_builder *b % endfor /* Convenience methods */ - -enum agx_bitop_table { - AGX_BITOP_NOR = 0x1, - AGX_BITOP_ANDN2 = 0x2, - AGX_BITOP_ANDN1 = 0x4, - AGX_BITOP_NOT = 0x5, - AGX_BITOP_XOR = 0x6, - AGX_BITOP_NAND = 0x7, - AGX_BITOP_AND = 0x8, - AGX_BITOP_XNOR = 0x9, - AGX_BITOP_MOV = 0xA, - AGX_BITOP_ORN2 = 0xB, - AGX_BITOP_ORN1 = 0xD, - AGX_BITOP_OR = 0xE -}; - -#define BINOP_BITOP(name, table) \ +#define BINOP_BITOP(name, expr) \ static inline agx_instr * \ agx_## name ##_to(agx_builder *b, agx_index dst0, agx_index src0, agx_index src1) \ { \ - return agx_bitop_to(b, dst0, src0, src1, AGX_BITOP_ ## table); \ + return agx_bitop_to(b, dst0, src0, src1, UTIL_LUT2(expr)); \ } \ \ static inline agx_index \ @@ -144,16 +129,16 @@ enum agx_bitop_table { return tmp; \ } -BINOP_BITOP(nor, NOR) -BINOP_BITOP(andn2, ANDN2) -BINOP_BITOP(andn1, ANDN1) -BINOP_BITOP(xor, XOR) -BINOP_BITOP(nand, NAND) -BINOP_BITOP(and, AND) -BINOP_BITOP(xnor, XNOR) -BINOP_BITOP(orn2, ORN2) -BINOP_BITOP(orn1, ORN1) -BINOP_BITOP(or, OR) +BINOP_BITOP(nor, ~(a | b)) +BINOP_BITOP(andn2, a & ~b) +BINOP_BITOP(andn1, ~a & b) +BINOP_BITOP(xor, a ^ b) +BINOP_BITOP(nand, ~(a & b)) +BINOP_BITOP(and, a & b) +BINOP_BITOP(xnor, ~a ^ b) +BINOP_BITOP(orn2, a | ~b) +BINOP_BITOP(orn1, ~a | b) +BINOP_BITOP(or, a | b) #undef BINOP_BITOP diff --git a/src/asahi/compiler/agx_lower_pseudo.c b/src/asahi/compiler/agx_lower_pseudo.c index 331a3cd2063..ac7650a5122 100644 --- a/src/asahi/compiler/agx_lower_pseudo.c +++ b/src/asahi/compiler/agx_lower_pseudo.c @@ -3,6 +3,7 @@ * SPDX-License-Identifier: MIT */ +#include "util/lut.h" #include "agx_builder.h" #include "agx_compiler.h" #include "agx_opcodes.h" @@ -76,10 +77,10 @@ lower(agx_builder *b, agx_instr *I) /* 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); + return agx_bitop_to(b, I->dest[0], I->src[0], agx_zero(), UTIL_LUT2(a)); case AGX_OPCODE_NOT: - return agx_bitop_to(b, I->dest[0], I->src[0], agx_zero(), AGX_BITOP_NOT); + return agx_bitop_to(b, I->dest[0], I->src[0], agx_zero(), UTIL_LUT2(~a)); /* We can sign-extend with an add */ case AGX_OPCODE_SIGNEXT: diff --git a/src/asahi/compiler/agx_optimizer.c b/src/asahi/compiler/agx_optimizer.c index 747d981ad5f..d7a81ae955c 100644 --- a/src/asahi/compiler/agx_optimizer.c +++ b/src/asahi/compiler/agx_optimizer.c @@ -3,6 +3,7 @@ * SPDX-License-Identifier: MIT */ +#include "util/lut.h" #include "util/macros.h" #include "agx_builder.h" #include "agx_compiler.h" @@ -415,7 +416,7 @@ agx_optimizer_if_not(agx_instr **defs, agx_instr *I) agx_instr *def = defs[I->src[0].value]; if (def->op != AGX_OPCODE_BITOP || !agx_is_equiv(def->src[1], agx_immediate(1)) || - def->truth_table != AGX_BITOP_XOR) + def->truth_table != UTIL_LUT2(a ^ b)) return; /* Fuse */ @@ -513,20 +514,11 @@ agx_optimizer_bitop(agx_instr **defs, agx_instr *I) agx_index src = I->src[s]; agx_instr *def = defs[src.value]; - /* Check for not src */ - if (def->op != AGX_OPCODE_NOT) - continue; - - /* Select new operation */ - if (s == 0) { - I->truth_table = - ((I->truth_table & 0x5) << 1) | ((I->truth_table & 0xa) >> 1); - } else if (s == 1) { - I->truth_table = ((I->truth_table & 0x3) << 2) | (I->truth_table >> 2); + /* If we find a not, select new operation and fuse */ + if (def->op == AGX_OPCODE_NOT) { + I->truth_table = util_lut2_invert_source(I->truth_table, s); + I->src[s] = def->src[0]; } - - /* Fuse */ - I->src[s] = def->src[0]; } } diff --git a/src/asahi/compiler/agx_print.c b/src/asahi/compiler/agx_print.c index e6c29c6940d..de099dd005f 100644 --- a/src/asahi/compiler/agx_print.c +++ b/src/asahi/compiler/agx_print.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: MIT */ +#include "util/lut.h" #include "agx_builder.h" #include "agx_compiler.h" @@ -119,36 +120,23 @@ agx_print_index(agx_index index, bool is_float, FILE *fp) fprintf(fp, ".neg"); } -static struct agx_opcode_info -agx_get_opcode_info_for_print(const agx_instr *I) -{ - struct agx_opcode_info info = agx_opcodes_info[I->op]; - - if (I->op == AGX_OPCODE_BITOP) { - const char *bitops[16] = { - [AGX_BITOP_NOR] = "nor", [AGX_BITOP_ANDN2] = "andn2", - [AGX_BITOP_ANDN1] = "andn1", [AGX_BITOP_XOR] = "xor", - [AGX_BITOP_NAND] = "nand", [AGX_BITOP_AND] = "and", - [AGX_BITOP_XNOR] = "xnor", [AGX_BITOP_ORN2] = "orn2", - [AGX_BITOP_ORN1] = "orn1", [AGX_BITOP_OR] = "or", - }; - - if (bitops[I->truth_table] != NULL) { - info.name = bitops[I->truth_table]; - info.immediates &= ~AGX_IMMEDIATE_TRUTH_TABLE; - } - } - - return info; -} +static const char *lut2_to_function[16] = { + "zero", "nor", "andn2", "not2", "andn1", "not1", "xor", "nand", + "and", "xnor", "mov1", "orn2", "mov2", "orn1", "or", "one", +}; void agx_print_instr(const agx_instr *I, FILE *fp) { assert(I->op < AGX_NUM_OPCODES); - struct agx_opcode_info info = agx_get_opcode_info_for_print(I); + struct agx_opcode_info info = agx_opcodes_info[I->op]; bool print_comma = false; + if (I->op == AGX_OPCODE_BITOP) { + info.name = lut2_to_function[I->truth_table]; + info.immediates &= ~AGX_IMMEDIATE_TRUTH_TABLE; + } + fprintf(fp, " "); agx_foreach_dest(I, d) {