brw: Add initial support for different instruction kinds

Prepare code for supporting subclasses of brw_inst for certain
specialized kinds of instructions.  This will allow

- Move certain fields from brw_inst to the specialized one,
  reducing its size and making it easy to understand what applies
  to which instruction;
- Move certain control sources into the specialized inst type, which
  currently take a full brw_reg to encode small integers.  Reducing
  the overall sources we walk and care also might help the code
  in general.

Next commits will add the new instruction kinds.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36730>
This commit is contained in:
Caio Oliveira 2025-08-20 15:09:33 -07:00 committed by Marge Bot
parent 339a4e8680
commit b27f6621ae
4 changed files with 51 additions and 12 deletions

View file

@ -11,17 +11,25 @@
#include "brw_inst.h"
#include "brw_isa_info.h"
static brw_inst *
brw_alloc_inst(brw_shader &s, unsigned num_srcs)
static inline unsigned
brw_inst_kind_size(brw_inst_kind kind)
{
STATIC_ASSERT((sizeof(brw_inst) % alignof(brw_reg)) == 0);
return sizeof(brw_inst);
}
void *mem = ralloc_size(s.mem_ctx, sizeof(brw_inst) + num_srcs * sizeof(brw_reg));
memset(mem, 0, sizeof(brw_inst));
static brw_inst *
brw_alloc_inst(brw_shader &s, brw_inst_kind kind, unsigned num_srcs)
{
const unsigned inst_size = brw_inst_kind_size(kind);
assert((inst_size % alignof(brw_reg)) == 0);
void *mem = ralloc_size(s.mem_ctx, inst_size + num_srcs * sizeof(brw_reg));
memset(mem, 0, inst_size);
brw_inst *inst = (brw_inst *)mem;
if (num_srcs)
inst->src = (brw_reg *)((char*)mem + sizeof(brw_inst));
inst->src = (brw_reg *)((char*)mem + inst_size);
inst->sources = num_srcs;
return inst;
@ -34,8 +42,10 @@ brw_new_inst(brw_shader &s, enum opcode opcode, unsigned exec_size,
assert(exec_size != 0);
assert(dst.file != IMM && dst.file != UNIFORM);
brw_inst *inst = brw_alloc_inst(s, num_srcs);
brw_inst_kind kind = brw_inst_kind_for_opcode(opcode);
brw_inst *inst = brw_alloc_inst(s, kind, num_srcs);
inst->kind = kind;
inst->opcode = opcode;
inst->dst = dst;
inst->exec_size = exec_size;
@ -64,10 +74,11 @@ brw_new_inst(brw_shader &s, enum opcode opcode, unsigned exec_size,
brw_inst *
brw_clone_inst(brw_shader &s, const brw_inst *inst)
{
brw_inst *clone = brw_alloc_inst(s, inst->sources);
brw_inst *clone = brw_alloc_inst(s, inst->kind, inst->sources);
brw_reg *cloned_src = clone->src;
memcpy((void*)clone, inst, sizeof(brw_inst));
const unsigned inst_size = brw_inst_kind_size(inst->kind);
memcpy((void*)clone, inst, inst_size);
brw_exec_node_init(clone);
clone->src = cloned_src;
@ -96,7 +107,15 @@ brw_inst *
brw_transform_inst(brw_shader &s, brw_inst *inst, enum opcode new_opcode,
unsigned new_num_sources)
{
inst->opcode = new_opcode;
const brw_inst_kind kind = inst->kind;
const brw_inst_kind new_kind = brw_inst_kind_for_opcode(new_opcode);
assert(new_kind == BRW_KIND_BASE);
const unsigned inst_size = brw_inst_kind_size(kind);
const unsigned new_inst_size = brw_inst_kind_size(new_kind);
assert(new_inst_size <= inst_size);
if (new_num_sources == UINT_MAX)
new_num_sources = brw_num_sources_for_opcode(s, new_opcode);
assert(new_num_sources != UINT_MAX);
@ -109,10 +128,18 @@ brw_transform_inst(brw_shader &s, brw_inst *inst, enum opcode new_opcode,
}
inst->sources = new_num_sources;
inst->opcode = new_opcode;
inst->kind = new_kind;
return inst;
}
brw_inst_kind
brw_inst_kind_for_opcode(enum opcode opcode)
{
return BRW_KIND_BASE;
}
bool
brw_inst::is_send() const
{

View file

@ -39,8 +39,13 @@
struct bblock_t;
struct brw_shader;
struct brw_inst : public brw_exec_node {
public:
enum ENUM_PACKED brw_inst_kind {
BRW_KIND_BASE,
};
brw_inst_kind brw_inst_kind_for_opcode(enum opcode opcode);
struct brw_inst : brw_exec_node {
brw_inst() = delete;
brw_inst(const brw_inst&) = delete;
@ -153,6 +158,7 @@ public:
enum opcode opcode; /* BRW_OPCODE_* or FS_OPCODE_* */
enum brw_conditional_mod conditional_mod; /**< BRW_CONDITIONAL_* */
enum brw_predicate predicate;
brw_inst_kind kind;
tgl_swsb sched; /**< Scheduling info. */

View file

@ -241,6 +241,8 @@ operands_match(const brw_inst *a, const brw_inst *b, bool *negate)
static bool
instructions_match(brw_inst *a, brw_inst *b, bool *negate)
{
/* `Kind` is derived from opcode, so skipped. */
return a->opcode == b->opcode &&
a->exec_size == b->exec_size &&
a->group == b->group &&
@ -291,6 +293,8 @@ hash_inst(const void *v)
/* Skip ir and annotation - we don't care for equivalency purposes. */
/* Skip `kind` since it is derived from the opcode. */
const uint8_t u8data[] = {
inst->sources,
inst->exec_size,

View file

@ -304,6 +304,8 @@ brw_validate(const brw_shader &s)
uint32_t last_used_address_register[16] = {};
foreach_inst_in_block (brw_inst, inst, block) {
VAL_ASSERT_EQ(inst->kind, brw_inst_kind_for_opcode(inst->opcode));
brw_validate_instruction_phase(s, inst);
switch (inst->opcode) {