isaspec: add gen-based leaf bitset separation

This is necessary for some ops which have slightly different encoding on
a4xx/a5xx, but are otherwise identical. This helps keeping the compiler
from having to worry about these details and creating separate ops.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Reviewed-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14789>
This commit is contained in:
Ilia Mirkin 2022-01-29 01:40:16 -05:00
parent 40468430a4
commit b91b036322
4 changed files with 77 additions and 29 deletions

View File

@ -88,8 +88,8 @@ ${expr.get_c_name()}(struct decode_scope *scope)
* emit various tables when they have pointers to each other)
*/
%for name, bitset in isa.bitsets.items():
static const struct isa_bitset bitset_${bitset.get_c_name()};
%for name, bitset in isa.all_bitsets():
static const struct isa_bitset bitset_${bitset.get_c_name()}_gen_${bitset.gen_min};
%endfor
%for root_name, root in isa.roots.items():
@ -100,12 +100,12 @@ const struct isa_bitset *${root.get_c_name()}[];
* bitset tables:
*/
%for name, bitset in isa.bitsets.items():
%for name, bitset in isa.all_bitsets():
% for case in bitset.cases:
% for field_name, field in case.fields.items():
% if field.get_c_typename() == 'TYPE_BITSET':
% if len(field.params) > 0:
static const struct isa_field_params ${case.get_c_name()}_${field.get_c_name()} = {
static const struct isa_field_params ${case.get_c_name()}_gen_${bitset.gen_min}_${field.get_c_name()} = {
.num_params = ${len(field.params)},
.params = {
% for param in field.params:
@ -117,7 +117,7 @@ static const struct isa_field_params ${case.get_c_name()}_${field.get_c_name()}
% endif
% endif
% endfor
static const struct isa_case ${case.get_c_name()} = {
static const struct isa_case ${case.get_c_name()}_gen_${bitset.gen_min} = {
% if case.expr is not None:
.expr = &${isa.expressions[case.expr].get_c_name()},
% endif
@ -138,7 +138,7 @@ static const struct isa_case ${case.get_c_name()} = {
% if field.get_c_typename() == 'TYPE_BITSET':
.bitsets = ${isa.roots[field.type].get_c_name()},
% if len(field.params) > 0:
.params = &${case.get_c_name()}_${field.get_c_name()},
.params = &${case.get_c_name()}_gen_${bitset.gen_min}_${field.get_c_name()},
% endif
% endif
% if field.get_c_typename() == 'TYPE_ENUM':
@ -152,10 +152,10 @@ static const struct isa_case ${case.get_c_name()} = {
},
};
% endfor
static const struct isa_bitset bitset_${bitset.get_c_name()} = {
static const struct isa_bitset bitset_${bitset.get_c_name()}_gen_${bitset.gen_min} = {
<% pattern = bitset.get_pattern() %>
% if bitset.extends is not None:
.parent = &bitset_${isa.bitsets[bitset.extends].get_c_name()},
.parent = &bitset_${isa.bitsets[bitset.extends].get_c_name()}_gen_${isa.bitsets[bitset.extends].gen_min},
% endif
.name = "${name}",
.gen = {
@ -168,7 +168,7 @@ static const struct isa_bitset bitset_${bitset.get_c_name()} = {
.num_cases = ${len(bitset.cases)},
.cases = {
% for case in bitset.cases:
&${case.get_c_name()},
&${case.get_c_name()}_gen_${bitset.gen_min},
% endfor
},
};
@ -180,10 +180,12 @@ static const struct isa_bitset bitset_${bitset.get_c_name()} = {
%for root_name, root in isa.roots.items():
const struct isa_bitset *${root.get_c_name()}[] = {
% for leaf_name, leaf in isa.leafs.items():
% if leaf.get_root() == root:
&bitset_${leaf.get_c_name()},
% endif
% for leaf_name, leafs in isa.leafs.items():
% for leaf in leafs:
% if leaf.get_root() == root:
&bitset_${leaf.get_c_name()}_gen_${leaf.gen_min},
% endif
% endfor
% endfor
(void *)0
};

View File

@ -219,10 +219,17 @@ class State(object):
yield root
def encode_leafs(self, root):
for name, leaf in self.isa.leafs.items():
if leaf.get_root() != root:
continue
yield leaf
for name, leafs in self.isa.leafs.items():
for leaf in leafs:
if leaf.get_root() != root:
continue
yield leaf
def encode_leaf_groups(self, root):
for name, leafs in self.isa.leafs.items():
if leafs[0].get_root() != root:
continue
yield leafs
# expressions used in a bitset (case or field or recursively parent bitsets)
def bitset_used_exprs(self, bitset):
@ -514,12 +521,23 @@ encode${root.get_c_name()}(struct encode_state *s, struct bitset_params *p, ${ro
{
% if root.encode.case_prefix is not None:
switch (${root.get_c_name()}_case(s, src)) {
% for leaf in s.encode_leafs(root):
case ${s.case_name(root, leaf.name)}: {
% for leafs in s.encode_leaf_groups(root):
case ${s.case_name(root, leafs[0].name)}: {
% for leaf in leafs:
% if leaf.has_gen_restriction():
if (s->gen >= ${leaf.gen_min} && s->gen <= ${leaf.gen_max}) {
% endif
<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %>
bitmask_t val = uint64_t_to_bitmask(${hex(leaf.get_pattern().match)});
BITSET_OR(val.bitset, val.bitset, ${root.snippets[snippet]}(s, p, src).bitset);
return val;
% if leaf.has_gen_restriction():
}
% endif
% endfor
% if leaf.has_gen_restriction():
break;
% endif
}
% endfor
default:

View File

@ -356,6 +356,9 @@ class BitSet(object):
return min(self.gen_max, parent.get_gen_max())
return self.gen_max
def has_gen_restriction(self):
return self.gen_min != 0 or self.gen_max != (1 << 32) - 1
def get_c_name(self):
return get_c_name(self.name)
@ -417,9 +420,11 @@ class ISA(object):
self.roots = {}
# Table of leaf nodes of bitset hierarchies:
# Note that there may be multiple leaves for a particular name
# (distinguished by gen), so the values here are lists.
self.leafs = {}
# Table of all bitsets:
# Table of all non-ambiguous bitsets (i.e. no per-gen ambiguity):
self.bitsets = {}
# Max needed bitsize for one instruction
@ -464,15 +469,23 @@ class ISA(object):
else:
dbg("derived: " + b.name)
self.bitsets[b.name] = b
self.leafs[b.name] = b
self.leafs.setdefault(b.name, []).append(b)
def validate_isa(self):
# Do one-time fixups
# Remove non-leaf nodes from the leafs table:
for name, bitset in self.bitsets.items():
if bitset.extends is not None:
for name, bitsets in list(self.leafs.items()):
for bitset in bitsets:
if bitset.extends in self.leafs:
del self.leafs[bitset.extends]
def validate_isa(self):
# Fix multi-gen leaves in bitsets
for name, bitsets in self.leafs.items():
if len(bitsets) == 1:
continue
del self.bitsets[name]
# Validate that all bitset fields have valid types, and in
# the case of bitset type, the sizes match:
builtin_types = ['branch', 'int', 'uint', 'hex', 'offset', 'uoffset', 'float', 'bool', 'enum']
@ -502,11 +515,12 @@ class ISA(object):
# Validate that all the leaf node bitsets have no remaining
# undefined bits
for name, bitset in self.leafs.items():
pat = bitset.get_pattern()
sz = bitset.get_size()
assert ((pat.mask | pat.field_mask) == (1 << sz) - 1), "leaf bitset {} has undefined bits: {:x}".format(
bitset.name, ~(pat.mask | pat.field_mask) & ((1 << sz) - 1))
for name, bitsets in self.leafs.items():
for bitset in bitsets:
pat = bitset.get_pattern()
sz = bitset.get_size()
assert ((pat.mask | pat.field_mask) == (1 << sz) - 1), "leaf bitset {} has undefined bits: {:x}".format(
bitset.name, ~(pat.mask | pat.field_mask) & ((1 << sz) - 1))
# TODO somehow validating that only one bitset in a hierarchy
# matches any given bit pattern would be useful.
@ -551,3 +565,14 @@ class ISA(object):
parts.append('0x0')
return parts
# Returns all bitsets in the ISA, including all per-gen variants, in
# (name, bitset) pairs.
def all_bitsets(self):
for name, bitset in self.bitsets.items():
yield name, bitset
for name, bitsets in self.leafs.items():
if len(bitsets) == 1:
continue
for bitset in bitsets:
yield name, bitset

View File

@ -33,6 +33,8 @@
struct bitset_params;
struct encode_state {
unsigned gen;
struct ir3_compiler *compiler;
/**
@ -321,6 +323,7 @@ isa_assemble(struct ir3_shader_variant *v)
foreach_block (block, &shader->block_list) {
foreach_instr (instr, &block->instr_list) {
struct encode_state s = {
.gen = shader->compiler->gen * 100,
.compiler = shader->compiler,
.instr = instr,
};