From 0727b7a07992618451d0d3d610b4af71dc693ce7 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 17 Jan 2025 10:55:42 -0500 Subject: [PATCH] nir: introduce bindgen_return with vtn_bindgen2, we'll want return values without derefs. this needs some special handholding. Signed-off-by: Alyssa Rosenzweig Reviewed-by: Lionel Landwerlin Reviewed-by: Mary Guillemard Part-of: --- src/compiler/nir/nir.h | 8 ++++---- src/compiler/nir/nir_functions.c | 26 ++++++++++++++++++-------- src/compiler/nir/nir_intrinsics.py | 4 ++++ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 62703855e1c..f21b598a8bd 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -5581,10 +5581,10 @@ bool nir_split_struct_vars(nir_shader *shader, nir_variable_mode modes); bool nir_lower_returns_impl(nir_function_impl *impl); bool nir_lower_returns(nir_shader *shader); -void nir_inline_function_impl(struct nir_builder *b, - const nir_function_impl *impl, - nir_def **params, - struct hash_table *shader_var_remap); +nir_def *nir_inline_function_impl(struct nir_builder *b, + const nir_function_impl *impl, + nir_def **params, + struct hash_table *shader_var_remap); bool nir_inline_functions(nir_shader *shader); void nir_cleanup_functions(nir_shader *shader); bool nir_link_shader_functions(nir_shader *shader, diff --git a/src/compiler/nir/nir_functions.c b/src/compiler/nir/nir_functions.c index 514e831920c..1468a5900b4 100644 --- a/src/compiler/nir/nir_functions.c +++ b/src/compiler/nir/nir_functions.c @@ -96,7 +96,7 @@ fixup_cast_deref_mode(nir_deref_instr *deref) } } -void +nir_def * nir_inline_function_impl(struct nir_builder *b, const nir_function_impl *impl, nir_def **params, @@ -106,6 +106,11 @@ nir_inline_function_impl(struct nir_builder *b, exec_list_append(&b->impl->locals, ©->locals); + /* Normally, NIR function returns are deref based, but for bindgen, we use a + * sideband here to let us lower derefs ahead-of-time. + */ + nir_def *ret_val = NULL; + nir_foreach_block(block, copy) { nir_foreach_instr_safe(instr, block) { switch (instr->type) { @@ -152,13 +157,16 @@ nir_inline_function_impl(struct nir_builder *b, } case nir_instr_type_intrinsic: { - nir_intrinsic_instr *load = nir_instr_as_intrinsic(instr); - if (load->intrinsic != nir_intrinsic_load_param) - break; - - unsigned param_idx = nir_intrinsic_param_idx(load); - assert(param_idx < impl->function->num_params); - nir_def_replace(&load->def, params[param_idx]); + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + if (intr->intrinsic == nir_intrinsic_bindgen_return) { + assert(ret_val == NULL && "expected exactly one return write"); + ret_val = intr->src[0].ssa; + nir_instr_remove(&intr->instr); + } else if (intr->intrinsic == nir_intrinsic_load_param) { + unsigned param_idx = nir_intrinsic_param_idx(intr); + assert(param_idx < impl->function->num_params); + nir_def_replace(&intr->def, params[param_idx]); + } break; } @@ -191,6 +199,8 @@ nir_inline_function_impl(struct nir_builder *b, nir_cf_reinsert(&body, nir_before_instr(&nop->instr)); b->cursor = nir_instr_remove(&nop->instr); } + + return ret_val; } static bool inline_function_impl(nir_function_impl *impl, struct set *inlined); diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 7baec7724bc..d53d123ddbf 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -340,6 +340,10 @@ intrinsic("convert_alu_types", dest_comp=0, src_comp=[0], intrinsic("load_param", dest_comp=0, indices=[PARAM_IDX], flags=[CAN_ELIMINATE]) +# Store a scalar value to be used as a return value. Usually store_deref is used +# for this, but vtn_bindgen needs to lower derefs. +intrinsic("bindgen_return", src_comp=[0]) + intrinsic("load_deref", dest_comp=0, src_comp=[-1], indices=[ACCESS], flags=[CAN_ELIMINATE]) intrinsic("store_deref", src_comp=[-1, 0], indices=[WRITE_MASK, ACCESS])