From 9a88dff9f4db038645e0200f9d5c1859835d971d Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Wed, 6 May 2026 12:55:06 -0400 Subject: [PATCH] i915/corm: add temporary register tracking and dead temp release Track the last use of each SSA def and release temporary registers as soon as they're dead, allowing more aggressive temp reuse. Includes the register aliasing fix for mov/fneg: these ops alias the def to the source register, so the source's lifetime must be extended to match the def's to prevent premature release. shader-db (I915_FS=nir): 52/403 compiled, 231 alu shader-db (I915_FS=both): nir won 52 (26 identical, 16 tied, 9 better, 1 only), 233 TGSI, 118 neither Assisted-by: Claude --- src/gallium/drivers/i915/i915_fpc_nir.c | 54 +++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/gallium/drivers/i915/i915_fpc_nir.c b/src/gallium/drivers/i915/i915_fpc_nir.c index 346e06d0a34..4df750d4734 100644 --- a/src/gallium/drivers/i915/i915_fpc_nir.c +++ b/src/gallium/drivers/i915/i915_fpc_nir.c @@ -22,8 +22,51 @@ struct nir_to_i915 { uint32_t *ureg_map; unsigned ureg_map_size; + + int *last_use; + int ip; }; +static bool +mark_last_use_cb(nir_src *src, void *state) +{ + struct nir_to_i915 *c = state; + if (src->ssa->index < c->ureg_map_size) + c->last_use[src->ssa->index] = c->ip; + return true; +} + +static void +compute_last_use(struct nir_to_i915 *c, nir_function_impl *impl) +{ + c->ip = 0; + nir_foreach_block(block, impl) { + nir_foreach_instr(instr, block) { + nir_foreach_src(instr, mark_last_use_cb, c); + c->ip++; + } + } +} + +static bool +release_if_last_use_cb(nir_src *src, void *state) +{ + struct nir_to_i915 *c = state; + unsigned idx = src->ssa->index; + if (idx < c->ureg_map_size && c->last_use[idx] == c->ip) { + uint32_t ureg = c->ureg_map[idx]; + if (GET_UREG_TYPE(ureg) == REG_TYPE_R) + i915_release_temp(c->p, GET_UREG_NR(ureg)); + } + return true; +} + +static void +release_dead_temps(struct nir_to_i915 *c, nir_instr *instr) +{ + nir_foreach_src(instr, release_if_last_use_cb, c); +} + static void set_ureg(struct nir_to_i915 *c, nir_def *def, uint32_t ureg) { @@ -185,6 +228,9 @@ emit_alu(struct nir_to_i915 *c, nir_alu_instr *alu) i915_release_temp(p, GET_UREG_NR(dest)); set_ureg(c, def, alu->op == nir_op_fneg ? negate(src0, 1, 1, 1, 1) : src0); + unsigned src_idx = alu->src[0].src.ssa->index; + if (c->last_use[src_idx] == c->ip) + c->last_use[src_idx] = c->last_use[def->index]; return; } case nir_op_fabs: @@ -727,13 +773,20 @@ i915_translate_fragment_program_nir(struct i915_context *i915, .opts = *opts, .ureg_map_size = impl->ssa_alloc, .ureg_map = CALLOC(impl->ssa_alloc, sizeof(uint32_t)), + .last_use = CALLOC(impl->ssa_alloc, sizeof(int)), }; + memset(c.last_use, -1, impl->ssa_alloc * sizeof(int)); + compute_last_use(&c, impl); + + c.ip = 0; nir_foreach_block(block, impl) { nir_foreach_instr(instr, block) { emit_instr(&c, instr); if (p->error[0]) break; + release_dead_temps(&c, instr); + c.ip++; } if (p->error[0]) break; @@ -799,6 +852,7 @@ cleanup: else ralloc_free(p->error); + FREE(c.last_use); FREE(c.ureg_map); FREE(p);