[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