[Mesa-dev] [PATCH 07/12] glsl: Sometimes use a switch-statment in get_intrinsic_opcode
Ian Romanick
idr at freedesktop.org
Tue Jul 19 20:13:09 UTC 2016
From: Ian Romanick <ian.d.romanick at 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.romanick at 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 c2b78a0..3c2c76c 100644
--- a/src/compiler/glsl/nir_intrinsic_map.py
+++ b/src/compiler/glsl/nir_intrinsic_map.py
@@ -73,6 +73,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.
@@ -130,48 +150,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
More information about the mesa-dev
mailing list