From 07530127669cc3efa6c99cc69ccfbca5582a98b5 Mon Sep 17 00:00:00 2001 From: Natalie Vock Date: Wed, 28 Jan 2026 12:05:36 +0100 Subject: [PATCH] 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: (cherry picked from commit ad23e02a2809c33693c358336dbc9459cbab831f) --- .pick_status.json | 2 +- src/amd/compiler/aco_nir_call_attribs.h | 8 +++++++- .../compiler/instruction_selection/aco_isel_helpers.cpp | 6 ++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 3e230bb8e4d..0e25b04e3f4 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -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 diff --git a/src/amd/compiler/aco_nir_call_attribs.h b/src/amd/compiler/aco_nir_call_attribs.h index d74fa63c969..777f1063c05 100644 --- a/src/amd/compiler/aco_nir_call_attribs.h +++ b/src/amd/compiler/aco_nir_call_attribs.h @@ -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, }; diff --git a/src/amd/compiler/instruction_selection/aco_isel_helpers.cpp b/src/amd/compiler/instruction_selection/aco_isel_helpers.cpp index f9bff68dce2..4255128bbd0 100644 --- a/src/amd/compiler/instruction_selection/aco_isel_helpers.cpp +++ b/src/amd/compiler/instruction_selection/aco_isel_helpers.cpp @@ -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());