aco: Don't exclude discardable parameters from register preservation

The original semantic of discardable parameters was "okay, nothing
actually uses this parameter, feel free to clobber it", but we were
only using it with tail calls from a function without discardable
parameters, which was broken.

Instead, slightly change the use-case and utilize the "discardable"
attribute to mark parameters that the callee will clobber in a tail
call. This makes doing tail calls safe when the tail callee receives a
modified set of parameters.

Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39579>
(cherry picked from commit ad23e02a28)
This commit is contained in:
Natalie Vock 2026-01-28 12:05:36 +01:00 committed by Eric Engestrom
parent 7b1c9adfea
commit 0753012766
3 changed files with 10 additions and 6 deletions

View file

@ -1634,7 +1634,7 @@
"description": "aco: Don't exclude discardable parameters from register preservation",
"nominated": true,
"nomination_type": 1,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null,
"notes": null

View file

@ -22,7 +22,13 @@ enum aco_nir_function_attribs {
};
enum aco_nir_parameter_attribs {
/* Parameter value is not used by any callee and does not need to be preserved */
/* This parameter's value may not be preserved across a callee. Unlike return parameters, the
* parameter's value is undefined on return. Callers must back up values of discardable
* parameters separately.
* Mostly used for tail calls, where parameters to the tail callee have different values than
* for the caller. In that case, on function return, the parameters will have been overwritten
* with the tail callee parameter values.
*/
ACO_NIR_PARAM_ATTRIB_DISCARDABLE = 0x1,
};

View file

@ -1034,8 +1034,7 @@ find_param_regs(Program* program, const ABI& abi, callee_info& info,
param_demand += Temp(0, it2->rc);
it2->dst_info->needs_explicit_preservation =
regs == clobbered_regs && !it2->dst_info->discardable;
it2->dst_info->needs_explicit_preservation = regs == clobbered_regs;
it2->dst_info->def.setPrecolored(*next_reg);
for (unsigned i = 0; i < it2->rc.size(); ++i)
BITSET_CLEAR(regs, next_reg->reg() + i);
@ -1051,8 +1050,7 @@ find_param_regs(Program* program, const ABI& abi, callee_info& info,
next_reg = next_reg->advance(required_padding * 4);
}
if (next_reg) {
params.back().dst_info->needs_explicit_preservation =
regs == clobbered_regs && !params.back().dst_info->discardable;
params.back().dst_info->needs_explicit_preservation = regs == clobbered_regs;
param_demand += Temp(0, params.back().rc);
params.back().dst_info->def.setPrecolored(*next_reg);
BITSET_CLEAR_COUNT(regs, next_reg->reg(), params.back().rc.size());