|
|
|
@@ -26,6 +26,56 @@ |
|
|
|
#include "nir_control_flow.h" |
|
|
|
#include "nir_vla.h" |
|
|
|
|
|
|
|
void nir_inline_function_impl(struct nir_builder *b, |
|
|
|
const nir_function_impl *impl, |
|
|
|
nir_ssa_def **params) |
|
|
|
{ |
|
|
|
nir_function_impl *copy = nir_function_impl_clone(b->shader, impl); |
|
|
|
|
|
|
|
/* Insert a nop at the cursor so we can keep track of where things are as |
|
|
|
* we add/remove stuff from the CFG. |
|
|
|
*/ |
|
|
|
nir_intrinsic_instr *nop = |
|
|
|
nir_intrinsic_instr_create(b->shader, nir_intrinsic_nop); |
|
|
|
nir_builder_instr_insert(b, &nop->instr); |
|
|
|
|
|
|
|
exec_list_append(&b->impl->locals, ©->locals); |
|
|
|
exec_list_append(&b->impl->registers, ©->registers); |
|
|
|
|
|
|
|
nir_foreach_block(block, copy) { |
|
|
|
nir_foreach_instr_safe(instr, block) { |
|
|
|
/* Returns have to be lowered for this to work */ |
|
|
|
assert(instr->type != nir_instr_type_jump || |
|
|
|
nir_instr_as_jump(instr)->type != nir_jump_return); |
|
|
|
|
|
|
|
if (instr->type != nir_instr_type_intrinsic) |
|
|
|
continue; |
|
|
|
|
|
|
|
nir_intrinsic_instr *load = nir_instr_as_intrinsic(instr); |
|
|
|
if (load->intrinsic != nir_intrinsic_load_param) |
|
|
|
continue; |
|
|
|
|
|
|
|
unsigned param_idx = nir_intrinsic_param_idx(load); |
|
|
|
assert(param_idx < impl->function->num_params); |
|
|
|
assert(load->dest.is_ssa); |
|
|
|
nir_ssa_def_rewrite_uses(&load->dest.ssa, |
|
|
|
nir_src_for_ssa(params[param_idx])); |
|
|
|
|
|
|
|
/* Remove any left-over load_param intrinsics because they're soon |
|
|
|
* to be in another function and therefore no longer valid. |
|
|
|
*/ |
|
|
|
nir_instr_remove(&load->instr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* Pluck the body out of the function and place it here */ |
|
|
|
nir_cf_list body; |
|
|
|
nir_cf_list_extract(&body, ©->body); |
|
|
|
nir_cf_reinsert(&body, nir_before_instr(&nop->instr)); |
|
|
|
|
|
|
|
b->cursor = nir_instr_remove(&nop->instr); |
|
|
|
} |
|
|
|
|
|
|
|
static bool inline_function_impl(nir_function_impl *impl, struct set *inlined); |
|
|
|
|
|
|
|
static bool |
|
|
|
@@ -49,16 +99,10 @@ inline_functions_block(nir_block *block, nir_builder *b, |
|
|
|
nir_call_instr *call = nir_instr_as_call(instr); |
|
|
|
assert(call->callee->impl); |
|
|
|
|
|
|
|
/* Make sure that the function we're calling is already inlined */ |
|
|
|
inline_function_impl(call->callee->impl, inlined); |
|
|
|
|
|
|
|
nir_function_impl *callee_copy = |
|
|
|
nir_function_impl_clone(call->callee->impl); |
|
|
|
callee_copy->function = call->callee; |
|
|
|
|
|
|
|
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); |
|
|
|
b->cursor = nir_instr_remove(&call->instr); |
|
|
|
|
|
|
|
/* Rewrite all of the uses of the callee's parameters to use the call |
|
|
|
* instructions sources. In order to ensure that the "load" happens |
|
|
|
@@ -72,34 +116,7 @@ inline_functions_block(nir_block *block, nir_builder *b, |
|
|
|
call->callee->params[i].num_components); |
|
|
|
} |
|
|
|
|
|
|
|
nir_foreach_block(block, callee_copy) { |
|
|
|
nir_foreach_instr_safe(instr, block) { |
|
|
|
if (instr->type != nir_instr_type_intrinsic) |
|
|
|
continue; |
|
|
|
|
|
|
|
nir_intrinsic_instr *load = nir_instr_as_intrinsic(instr); |
|
|
|
if (load->intrinsic != nir_intrinsic_load_param) |
|
|
|
continue; |
|
|
|
|
|
|
|
unsigned param_idx = nir_intrinsic_param_idx(load); |
|
|
|
assert(param_idx < num_params); |
|
|
|
assert(load->dest.is_ssa); |
|
|
|
nir_ssa_def_rewrite_uses(&load->dest.ssa, |
|
|
|
nir_src_for_ssa(params[param_idx])); |
|
|
|
|
|
|
|
/* Remove any left-over load_param intrinsics because they're soon |
|
|
|
* to be in another function and therefore no longer valid. |
|
|
|
*/ |
|
|
|
nir_instr_remove(&load->instr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* Pluck the body out of the function and place it here */ |
|
|
|
nir_cf_list body; |
|
|
|
nir_cf_list_extract(&body, &callee_copy->body); |
|
|
|
nir_cf_reinsert(&body, b->cursor); |
|
|
|
|
|
|
|
nir_instr_remove(&call->instr); |
|
|
|
nir_inline_function_impl(b, call->callee->impl, params); |
|
|
|
} |
|
|
|
|
|
|
|
return progress; |