From: Ian Romanick <ian.d.roman...@intel.com> All of this code operates on the assumption that get_intrinsic_opcode will only be called with valid names. If the first character of every node in the trie level is unique, the prefix can be uniquely identified by switching on just that first character. Otherwise we have to string compare with the prefix. The switch-statement is quite a bit more compact that the if-statement ladder of string compares.
text data bss dec hex filename 7528835 273096 28584 7830515 777bf3 /tmp/i965_dri-64bit-before.so 7528339 273096 28584 7830019 777a03 /tmp/i965_dri-64bit-after.so Signed-off-by: Ian Romanick <ian.d.roman...@intel.com> --- src/compiler/glsl/nir_intrinsic_map.py | 101 +++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 23 deletions(-) diff --git a/src/compiler/glsl/nir_intrinsic_map.py b/src/compiler/glsl/nir_intrinsic_map.py index 69d2360..07b2d0d 100644 --- a/src/compiler/glsl/nir_intrinsic_map.py +++ b/src/compiler/glsl/nir_intrinsic_map.py @@ -72,6 +72,26 @@ def remove_prefix(table, prefix_length): return [(s[prefix_length:], d) for (s, d) in table] +def first_character_always_unique(trie): + """Determine whether the first character in every node in the trie level is + unique. + + """ + seen_characters = set() + for (s, t, d) in trie: + if s == "": + c = "" + else: + c = s[:1] + + if c in seen_characters: + return False + else: + seen_characters.add(c) + + return True + + def generate_trie(table): """table is a list of (string, data) tuples. It is assumed to be sorted by string. @@ -129,48 +149,83 @@ def generate_trie(table): return trie_level -def emit_trie_leaf(indent, d): +def emit_trie_leaf(indent, d, inside_switch): if d[1] is None: return "{}return {};\n".format(indent, d[0]) else: c_code = "{}int_op = {};\n".format(indent, d[0]) c_code += "{}uint_op = {};\n".format(indent, d[1]) + if inside_switch: + c_code += "{}break;\n".format(indent) return c_code def trie_as_C_code(trie, indent=" ", prefix_string="__intrinsic_"): offset = len(prefix_string) - conditional = "if" - c_code = "" - for (s, t, d) in trie: - if d is not None: - c_code += "{}{} (name[{}] == '\\0') {{\n".format(indent, conditional, offset) - c_code += "{} assert(strcmp(name, \"{}\") == 0);\n".format(indent, prefix_string) - c_code += emit_trie_leaf(indent + " ", d); - else: - # Before emitting the string comparison, check to see of the - # subtree has a single element with an empty string. In that - # case, use strcmp() instead of strncmp(). + # If the first character of every node in the trie level is unique, the + # prefix can be uniquely identified by switching on just that first + # character. Otherwise we have to string compare with the prefix. + if first_character_always_unique(trie): + c_code += "{}switch(name[{}]) {{\n".format(indent, offset) + + for (s, t, d) in trie: + if d is not None: + c_code += "{}case '\\0':\n".format(indent) + c_code += "{} assert(strcmp(name, \"{}\") == 0);\n".format(indent, prefix_string) + c_code += emit_trie_leaf(indent + " ", d, True); - if len(t) == 1 and t[0][2] is not None: - if s == "": - c_code += "{}{} (name[{}] == '\\0') {{\n".format(indent, conditional, offset) + else: + if len(t) == 1 and t[0][2] is not None: + if s == "": + c_code += "{}case '\\0':\n".format(indent) + else: + c_code += "{}case '{}':\n".format(indent, s[0]) + + c_code += "{} assert(strcmp(name, \"{}\") == 0);\n".format(indent, prefix_string + s) + c_code += emit_trie_leaf(indent + " ", t[0][2], True); else: - c_code += "{}{} (strcmp(name + {}, \"{}\") == 0) {{\n".format(indent, conditional, offset, s) + c_code += "{}case '{}':\n".format(indent, s[0]) + + c_code += trie_as_C_code(t, indent + " ", prefix_string + s) + c_code += "{} break;\n".format(indent) + + c_code += "{}default:\n".format(indent) + c_code += "{} unreachable(\"Invalid intrinsic name\");\n".format(indent) + c_code += "{}}}\n".format(indent) + else: + conditional = "if" + + for (s, t, d) in trie: + if d is not None: + c_code += "{}{} (name[{}] == '\\0') {{\n".format(indent, conditional, offset) + c_code += "{} assert(strcmp(name, \"{}\") == 0);\n".format(indent, prefix_string) + c_code += emit_trie_leaf(indent + " ", d, False); - c_code += "{} assert(strcmp(name, \"{}\") == 0);\n".format(indent, prefix_string + s) - c_code += emit_trie_leaf(indent + " ", t[0][2]); else: - c_code += "{}{} (strncmp(name + {}, \"{}\", {}) == 0) {{\n".format(indent, conditional, offset, s, len(s)) + # Before emitting the string comparison, check to see of the + # subtree has a single element with an empty string. In that + # case, use strcmp() instead of strncmp(). + + if len(t) == 1 and t[0][2] is not None: + if s == "": + c_code += "{}{} (name[{}] == '\\0') {{\n".format(indent, conditional, offset) + else: + c_code += "{}{} (strcmp(name + {}, \"{}\") == 0) {{\n".format(indent, conditional, offset, s) + + c_code += "{} assert(strcmp(name, \"{}\") == 0);\n".format(indent, prefix_string + s) + c_code += emit_trie_leaf(indent + " ", t[0][2], False); + else: + c_code += "{}{} (strncmp(name + {}, \"{}\", {}) == 0) {{\n".format(indent, conditional, offset, s, len(s)) + + c_code += trie_as_C_code(t, indent + " ", prefix_string + s) - c_code += trie_as_C_code(t, indent + " ", prefix_string + s) + conditional = "} else if" - conditional = "} else if" + c_code += "{}}} else\n".format(indent) + c_code += "{} unreachable(\"Invalid intrinsic name\");\n\n".format(indent) - c_code += "{}}} else\n".format(indent) - c_code += "{} unreachable(\"Invalid intrinsic name\");\n\n".format(indent) return c_code -- 2.5.5 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev