From d00a43f682c395a22e7037174600e1805a8403b6 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Sun, 18 Dec 2022 11:43:09 -0500 Subject: [PATCH] agx: Hash agx_instr faster 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 Part-of: --- src/asahi/compiler/agx_compiler.h | 2 ++ src/asahi/compiler/agx_opt_cse.c | 43 +++++-------------------------- 2 files changed, 9 insertions(+), 36 deletions(-) diff --git a/src/asahi/compiler/agx_compiler.h b/src/asahi/compiler/agx_compiler.h index f5ec42b47eb..232dc815db1 100644 --- a/src/asahi/compiler/agx_compiler.h +++ b/src/asahi/compiler/agx_compiler.h @@ -352,6 +352,8 @@ typedef struct { /* Output modifiers */ bool saturate : 1; unsigned mask : 4; + + unsigned padding : 11; } agx_instr; static inline void diff --git a/src/asahi/compiler/agx_opt_cse.c b/src/asahi/compiler/agx_opt_cse.c index 359a5ed42ac..a62fb1f2cbd 100644 --- a/src/asahi/compiler/agx_opt_cse.c +++ b/src/asahi/compiler/agx_opt_cse.c @@ -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; }