From 9d503aea069e08cffd57a4d590a6a0ca3b8ae4a2 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Fri, 15 Jul 2016 15:44:32 -0700 Subject: [PATCH] nir/inline: Constant-initialize local variables in the callee if needed Signed-off-by: Jason Ekstrand Reviewed-by: Kenneth Graunke Cc: "12.0" --- src/compiler/nir/nir_inline_functions.c | 42 +++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/compiler/nir/nir_inline_functions.c b/src/compiler/nir/nir_inline_functions.c index c36748d..cf31e14 100644 --- a/src/compiler/nir/nir_inline_functions.c +++ b/src/compiler/nir/nir_inline_functions.c @@ -25,6 +25,20 @@ #include "nir_builder.h" #include "nir_control_flow.h" +static bool +deref_apply_constant_initializer(nir_deref_var *deref, void *state) +{ + struct nir_builder *b = state; + + nir_load_const_instr *initializer = + nir_deref_get_const_initializer_load(b->shader, deref); + nir_builder_instr_insert(b, &initializer->instr); + + nir_store_deref_var(b, deref, &initializer->def, 0xf); + + return true; +} + static bool inline_function_impl(nir_function_impl *impl, struct set *inlined); static void @@ -174,11 +188,35 @@ inline_functions_block(nir_block *block, nir_builder *b, /* Add copies of all in parameters */ assert(call->num_params == callee_copy->num_params); + b->cursor = nir_before_instr(&call->instr); + + /* Before we insert the copy of the function, we need to lower away + * constant initializers on local variables. This is because constant + * initializers happen (effectively) at the top of the function and, + * since these are about to become locals of the calling function, + * initialization will happen at the top of the caller rather than at + * the top of the callee. This isn't usually a problem, but if we are + * being inlined inside of a loop, it can result in the variable not + * getting re-initialized properly for all loop iterations. + */ + nir_foreach_variable(local, &callee_copy->locals) { + if (!local->constant_initializer) + continue; + + nir_deref_var deref; + deref.deref.deref_type = nir_deref_type_var, + deref.deref.child = NULL; + deref.deref.type = local->type, + deref.var = local; + + nir_deref_foreach_leaf(&deref, deref_apply_constant_initializer, b); + + local->constant_initializer = NULL; + } + exec_list_append(&b->impl->locals, &callee_copy->locals); exec_list_append(&b->impl->registers, &callee_copy->registers); - b->cursor = nir_before_instr(&call->instr); - /* We now need to tie the two functions together using the * parameters. There are two ways we do this: One is to turn the * parameter into a local variable and do a shadow-copy. The other -- 2.7.4