agx: Hash agx_instr faster
authorAlyssa Rosenzweig <alyssa@rosenzweig.io>
Sun, 18 Dec 2022 16:43:09 +0000 (11:43 -0500)
committerAlyssa Rosenzweig <alyssa@rosenzweig.io>
Thu, 5 Jan 2023 16:49:22 +0000 (11:49 -0500)
Prior to this change, agx_opt_cse is our most expensive backend pass, due to the
time spent hashing instructions. hash_instr was calling into XXH32 a massive
number of times, often to hash only a single bit. It's much faster to hash
entire blocks of memory at a time. Optimize to do just that.

With this change, agx_opt_cse is now cheaper than instruction selection as
it should be.

No shader-db changes (except CPU time decrease).

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20446>

src/asahi/compiler/agx_compiler.h
src/asahi/compiler/agx_opt_cse.c

index f5ec42b..232dc81 100644 (file)
@@ -352,6 +352,8 @@ typedef struct {
    /* Output modifiers */
    bool saturate : 1;
    unsigned mask : 4;
+
+   unsigned padding : 11;
 } agx_instr;
 
 static inline void
index 359a5ed..a62fb1f 100644 (file)
@@ -23,53 +23,24 @@ HASH(uint32_t hash, unsigned data)
    return XXH32(&data, sizeof(data), hash);
 }
 
-static uint32_t
-hash_index(uint32_t hash, agx_index index)
-{
-   assert(!index.kill && "CSE is run early");
-   assert(!index.cache && "CSE is run early");
-   assert(!index.discard && "CSE is run early");
-
-   hash = HASH(hash, index.value);
-   hash = HASH(hash, index.abs);
-   hash = HASH(hash, index.neg);
-   hash = HASH(hash, index.size);
-   hash = HASH(hash, index.type);
-   return hash;
-}
-
-/* Hash an ALU instruction. */
+/* Hash an instruction. XXH32 isn't too speedy, so this is hotspot. */
 static uint32_t
 hash_instr(const void *data)
 {
    const agx_instr *I = data;
    uint32_t hash = 0;
 
-   hash = HASH(hash, I->op);
-   hash = HASH(hash, I->nr_dests);
-   hash = HASH(hash, I->nr_srcs);
-
    /* Explcitly skip destinations, except for size and type */
    agx_foreach_dest(I, d) {
-      hash = HASH(hash, I->dest[d].type);
-      hash = HASH(hash, I->dest[d].size);
+      hash = HASH(hash, ((uint32_t)I->dest[d].type) |
+                           (((uint32_t)I->dest[d].size) << 16));
    }
 
-   agx_foreach_src(I, s) {
-      hash = hash_index(hash, I->src[s]);
-   }
+   /* Hash the source array as-is */
+   hash = XXH32(I->src, sizeof(agx_index) * I->nr_srcs, hash);
 
-   /* Explicitly skip last, scoreboard, nest */
-
-   hash = HASH(hash, I->imm);
-   hash = HASH(hash, I->perspective);
-   hash = HASH(hash, I->invert_cond);
-   hash = HASH(hash, I->dim);
-   hash = HASH(hash, I->offset);
-   hash = HASH(hash, I->shadow);
-   hash = HASH(hash, I->shift);
-   hash = HASH(hash, I->saturate);
-   hash = HASH(hash, I->mask);
+   /* Hash everything else in the instruction starting from the opcode */
+   hash = XXH32(&I->op, sizeof(agx_instr) - offsetof(agx_instr, op), hash);
 
    return hash;
 }