agx: use util_lut2

While Intel will use the full feature set of util_lut3 in the future, AGX can
use the cut down 2-source versions right now to get us an in-tree user.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@intel.com>
Reviewed-by: Mary Guillemard <mary.guillemard@collabora.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37200>
This commit is contained in:
Alyssa Rosenzweig 2025-09-05 11:46:31 -04:00 committed by Marge Bot
parent a2d14208b0
commit 5f5fda147a
4 changed files with 33 additions and 67 deletions

View file

@ -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

View file

@ -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:

View file

@ -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];
}
}

View file

@ -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) {