freedreno/hw/isa: Add expression caching
authorRob Clark <robdclark@chromium.org>
Tue, 15 Dec 2020 21:22:37 +0000 (13:22 -0800)
committerMarge Bot <eric+marge@anholt.net>
Wed, 13 Jan 2021 18:32:47 +0000 (18:32 +0000)
Drops decoding an ~850KB collection of instructions from ~4min to ~1sec.

Granted for normal sized shaders, this probably doesn't matter.. but it
at reduces my cycle time for fixing things to match existing disasm
syntax using this massive collection of unique instructions.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7997>

src/freedreno/isa/decode.c

index 92d2664..89575d1 100644 (file)
@@ -32,6 +32,7 @@
 #include "util/bitset.h"
 #include "util/compiler.h"
 #include "util/half_float.h"
+#include "util/hash_table.h"
 #include "util/ralloc.h"
 #include "util/u_debug.h"
 #include "util/u_math.h"
@@ -92,6 +93,21 @@ struct decode_scope {
         * Pointer back to decode state, for convenience.
         */
        struct decode_state *state;
+
+       /**
+        * Cache expression evaluation results.  Expressions for overrides can
+        * be repeatedly evaluated for each field being resolved.  And each
+        * field reference to a derived field (potentially from another expr)
+        * would require re-evaluation.  But for a given scope, each evaluation
+        * of an expression gives the same result.  So we can cache to speed
+        * things up.
+        *
+        * TODO we could maybe be clever and assign a unique idx to each expr
+        * and use a direct lookup table?  Would be a bit more clever if it was
+        * smart enough to allow unrelated expressions that are never involved
+        * in a given scope to have overlapping cache lookup idx's.
+        */
+       struct hash_table *cache;
 };
 
 /**
@@ -225,6 +241,15 @@ pop_scope(struct decode_scope *scope)
 static uint64_t
 evaluate_expr(struct decode_scope *scope, isa_expr_t expr)
 {
+       if (scope->cache) {
+               struct hash_entry *entry = _mesa_hash_table_search(scope->cache, expr);
+               if (entry) {
+                       return *(uint64_t *)entry->data;
+               }
+       } else {
+               scope->cache = _mesa_pointer_hash_table_create(scope);
+       }
+
        if (!push_expr(scope->state, expr))
                return 0;
 
@@ -232,6 +257,10 @@ evaluate_expr(struct decode_scope *scope, isa_expr_t expr)
 
        pop_expr(scope->state);
 
+       uint64_t *retp = ralloc_size(scope->cache, sizeof(*retp));
+       *retp = ret;
+       _mesa_hash_table_insert(scope->cache, expr, retp);
+
        return ret;
 }