From 2b826582d805319fedbc211698e7eeb455d54101 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 25 Sep 2021 11:48:29 -0700 Subject: [PATCH] isaspec: De-duplicate bitset encoding bitset encoding tends to have a lot of duplication, for ex. many instructions with the same encoding modulo the fixed pattern. Now that encode_bitset is split out into it's own template, so that we can capture the result, use a hash table to de-duplicate the bitset encoding into "snippet" functions so that bitset cases with identical encoding can re-use the same generated code. Signed-off-by: Rob Clark Part-of: --- src/compiler/isaspec/encode.py | 23 +++++++++++++++++++++-- src/compiler/isaspec/isa.py | 4 ++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/compiler/isaspec/encode.py b/src/compiler/isaspec/encode.py index 7bd5d08a582..b581a5622d8 100755 --- a/src/compiler/isaspec/encode.py +++ b/src/compiler/isaspec/encode.py @@ -467,6 +467,21 @@ ${s.expr_name(leaf.get_root(), expr)}(struct encode_state *s, struct bitset_para */ %for root in s.encode_roots(): +% for leaf in s.encode_leafs(root): +<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %> +% if snippet not in root.snippets.keys(): +<% snippet_name = "snippet" + root.get_c_name() + "_" + str(len(root.snippets)) %> +static bitmask_t +${snippet_name}(struct encode_state *s, struct bitset_params *p, ${root.encode.type} src) +{ + bitmask_t val = uint64_t_to_bitmask(0); +${snippet} + return val; +} +<% root.snippets[snippet] = snippet_name %> +% endif +% endfor + static bitmask_t encode${root.get_c_name()}(struct encode_state *s, struct bitset_params *p, ${root.encode.type} src) { @@ -474,8 +489,10 @@ encode${root.get_c_name()}(struct encode_state *s, struct bitset_params *p, ${ro switch (${root.get_c_name()}_case(s, src)) { % for leaf in s.encode_leafs(root): case ${s.case_name(root, leaf.name)}: { +<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %> bitmask_t val = uint64_t_to_bitmask(${hex(leaf.get_pattern().match)}); - ${encode_bitset.render(s=s, root=root, leaf=leaf)} + BITSET_OR(val.bitset, val.bitset, ${root.snippets[snippet]}(s, p, src).bitset); + return val; } % endfor default: @@ -490,8 +507,10 @@ encode${root.get_c_name()}(struct encode_state *s, struct bitset_params *p, ${ro return uint64_t_to_bitmask(0); % else: # single case bitset, no switch % for leaf in s.encode_leafs(root): +<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %> bitmask_t val = uint64_t_to_bitmask(${hex(leaf.get_pattern().match)}); - ${encode_bitset.render(s=s, root=root, leaf=leaf)} + BITSET_OR(val.bitset, val.bitset, ${root.snippets[snippet]}(s, p, src).bitset); + return val; % endfor % endif } diff --git a/src/compiler/isaspec/isa.py b/src/compiler/isaspec/isa.py index d3264f25895..22b8991d4c9 100644 --- a/src/compiler/isaspec/isa.py +++ b/src/compiler/isaspec/isa.py @@ -248,6 +248,10 @@ class BitSet(object): self.xml = xml self.name = xml.attrib['name'] + # Used for generated encoder, to de-duplicate encoding for + # similar instructions: + self.snippets = {} + if 'size' in xml.attrib: assert('extends' not in xml.attrib) self.size = int(xml.attrib['size'])