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
This commit is contained in:
Adam Jackson 2026-05-06 12:55:06 -04:00
parent c6be264c2d
commit 9a88dff9f4

View file

@ -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);