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

Reply via email to