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:
parent
40468430a4
commit
b91b036322
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue