X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fopt_function_inlining.cpp;h=84a9e4fa0933d910bea5da697e272ea9e1af5b53;hb=263f829d2e9be6dab5375910a082ff1e511bb44b;hp=8fef358cc97b102c68d007bbdc5dcf348d632d69;hpb=2bf95c519e755146704f4942b1703d47d18bfeaa;p=mesa.git diff --git a/src/glsl/opt_function_inlining.cpp b/src/glsl/opt_function_inlining.cpp index 8fef358cc97..84a9e4fa093 100644 --- a/src/glsl/opt_function_inlining.cpp +++ b/src/glsl/opt_function_inlining.cpp @@ -27,7 +27,6 @@ * Replaces calls to functions with the body of the function. */ -#include #include "ir.h" #include "ir_visitor.h" #include "ir_function_inlining.h" @@ -36,9 +35,11 @@ #include "program/hash_table.h" static void -do_sampler_replacement(exec_list *instructions, - ir_variable *sampler, - ir_dereference *deref); +do_variable_replacement(exec_list *instructions, + ir_variable *orig, + ir_dereference *repl); + +namespace { class ir_function_inlining_visitor : public ir_hierarchical_visitor { public: @@ -54,7 +55,6 @@ public: virtual ir_visitor_status visit_enter(ir_expression *); virtual ir_visitor_status visit_enter(ir_call *); - virtual ir_visitor_status visit_enter(ir_assignment *); virtual ir_visitor_status visit_enter(ir_return *); virtual ir_visitor_status visit_enter(ir_texture *); virtual ir_visitor_status visit_enter(ir_swizzle *); @@ -62,25 +62,13 @@ public: bool progress; }; - -bool -automatic_inlining_predicate(ir_instruction *ir) -{ - ir_call *call = ir->as_call(); - - if (call && can_inline(call)) - return true; - - return false; -} +} /* unnamed namespace */ bool do_function_inlining(exec_list *instructions) { ir_function_inlining_visitor v; - do_expression_flattening(instructions, automatic_inlining_predicate); - v.run(instructions); return v.progress; @@ -90,12 +78,12 @@ static void replace_return_with_assignment(ir_instruction *ir, void *data) { void *ctx = ralloc_parent(ir); - ir_variable *retval = (ir_variable *)data; + ir_dereference *orig_deref = (ir_dereference *) data; ir_return *ret = ir->as_return(); if (ret) { if (ret->value) { - ir_rvalue *lhs = new(ctx) ir_dereference_variable(retval); + ir_rvalue *lhs = orig_deref->clone(ctx, NULL); ret->replace_with(new(ctx) ir_assignment(lhs, ret->value, NULL)); } else { /* un-valued return has to be the last return, or we shouldn't @@ -107,66 +95,54 @@ replace_return_with_assignment(ir_instruction *ir, void *data) } } -ir_rvalue * +void ir_call::generate_inline(ir_instruction *next_ir) { void *ctx = ralloc_parent(this); ir_variable **parameters; - int num_parameters; + unsigned num_parameters; int i; - ir_variable *retval = NULL; struct hash_table *ht; ht = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare); - num_parameters = 0; - foreach_iter(exec_list_iterator, iter_sig, this->callee->parameters) - num_parameters++; - + num_parameters = this->callee->parameters.length(); parameters = new ir_variable *[num_parameters]; - /* Generate storage for the return value. */ - if (!this->callee->return_type->is_void()) { - retval = new(ctx) ir_variable(this->callee->return_type, "_ret_val", - ir_var_auto); - next_ir->insert_before(retval); - } - /* Generate the declarations for the parameters to our inlined code, * and set up the mapping of real function body variables to ours. */ i = 0; - exec_list_iterator sig_param_iter = this->callee->parameters.iterator(); - exec_list_iterator param_iter = this->actual_parameters.iterator(); - for (i = 0; i < num_parameters; i++) { - ir_variable *sig_param = (ir_variable *) sig_param_iter.get(); - ir_rvalue *param = (ir_rvalue *) param_iter.get(); + foreach_two_lists(formal_node, &this->callee->parameters, + actual_node, &this->actual_parameters) { + ir_variable *sig_param = (ir_variable *) formal_node; + ir_rvalue *param = (ir_rvalue *) actual_node; /* Generate a new variable for the parameter. */ - if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) { - /* For samplers, we want the inlined sampler references - * referencing the passed in sampler variable, since that - * will have the location information, which an assignment of - * a sampler wouldn't. Fix it up below. + if (sig_param->type->contains_opaque()) { + /* For opaque types, we want the inlined variable references + * referencing the passed in variable, since that will have + * the location information, which an assignment of an opaque + * variable wouldn't. Fix it up below. */ parameters[i] = NULL; } else { parameters[i] = sig_param->clone(ctx, ht); - parameters[i]->mode = ir_var_auto; + parameters[i]->data.mode = ir_var_auto; - /* Remove the read-only decoration becuase we're going to write + /* Remove the read-only decoration because we're going to write * directly to this variable. If the cloned variable is left * read-only and the inlined function is inside a loop, the loop * analysis code will get confused. */ - parameters[i]->read_only = false; + parameters[i]->data.read_only = false; next_ir->insert_before(parameters[i]); } /* Move the actual param into our param variable if it's an 'in' type. */ - if (parameters[i] && (sig_param->mode == ir_var_in || - sig_param->mode == ir_var_const_in || - sig_param->mode == ir_var_inout)) { + if (parameters[i] && (sig_param->data.mode == ir_var_function_in || + sig_param->data.mode == ir_var_const_in || + sig_param->data.mode == ir_var_function_inout)) { ir_assignment *assign; assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(parameters[i]), @@ -174,38 +150,33 @@ ir_call::generate_inline(ir_instruction *next_ir) next_ir->insert_before(assign); } - sig_param_iter.next(); - param_iter.next(); + ++i; } exec_list new_instructions; /* Generate the inlined body of the function to a new list */ - foreach_iter(exec_list_iterator, iter, callee->body) { - ir_instruction *ir = (ir_instruction *)iter.get(); + foreach_in_list(ir_instruction, ir, &callee->body) { ir_instruction *new_ir = ir->clone(ctx, ht); new_instructions.push_tail(new_ir); - visit_tree(new_ir, replace_return_with_assignment, retval); + visit_tree(new_ir, replace_return_with_assignment, this->return_deref); } - /* If any samplers were passed in, replace any deref of the sampler - * with a deref of the sampler argument. + /* If any opaque types were passed in, replace any deref of the + * opaque variable with a deref of the argument. */ - param_iter = this->actual_parameters.iterator(); - sig_param_iter = this->callee->parameters.iterator(); - for (i = 0; i < num_parameters; i++) { - ir_instruction *const param = (ir_instruction *) param_iter.get(); - ir_variable *sig_param = (ir_variable *) sig_param_iter.get(); + foreach_two_lists(formal_node, &this->callee->parameters, + actual_node, &this->actual_parameters) { + ir_rvalue *const param = (ir_rvalue *) actual_node; + ir_variable *sig_param = (ir_variable *) formal_node; - if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) { + if (sig_param->type->contains_opaque()) { ir_dereference *deref = param->as_dereference(); assert(deref); - do_sampler_replacement(&new_instructions, sig_param, deref); + do_variable_replacement(&new_instructions, sig_param, deref); } - param_iter.next(); - sig_param_iter.next(); } /* Now push those new instructions in. */ @@ -215,15 +186,14 @@ ir_call::generate_inline(ir_instruction *next_ir) * variables to our own. */ i = 0; - param_iter = this->actual_parameters.iterator(); - sig_param_iter = this->callee->parameters.iterator(); - for (i = 0; i < num_parameters; i++) { - ir_instruction *const param = (ir_instruction *) param_iter.get(); - const ir_variable *const sig_param = (ir_variable *) sig_param_iter.get(); + foreach_two_lists(formal_node, &this->callee->parameters, + actual_node, &this->actual_parameters) { + ir_rvalue *const param = (ir_rvalue *) actual_node; + const ir_variable *const sig_param = (ir_variable *) formal_node; /* Move our param variable into the actual param if it's an 'out' type. */ - if (parameters[i] && (sig_param->mode == ir_var_out || - sig_param->mode == ir_var_inout)) { + if (parameters[i] && (sig_param->data.mode == ir_var_function_out || + sig_param->data.mode == ir_var_function_inout)) { ir_assignment *assign; assign = new(ctx) ir_assignment(param->clone(ctx, NULL)->as_rvalue(), @@ -232,18 +202,12 @@ ir_call::generate_inline(ir_instruction *next_ir) next_ir->insert_before(assign); } - param_iter.next(); - sig_param_iter.next(); + ++i; } delete [] parameters; hash_table_dtor(ht); - - if (retval) - return new(ctx) ir_dereference_variable(retval); - else - return NULL; } @@ -283,13 +247,7 @@ ir_visitor_status ir_function_inlining_visitor::visit_enter(ir_call *ir) { if (can_inline(ir)) { - /* If the call was part of some tree, then it should have been - * flattened out or we shouldn't have seen it because of a - * visit_continue_with_parent in this visitor. - */ - assert(ir == base_ir); - - (void) ir->generate_inline(ir); + ir->generate_inline(ir); ir->remove(); this->progress = true; } @@ -298,43 +256,24 @@ ir_function_inlining_visitor::visit_enter(ir_call *ir) } -ir_visitor_status -ir_function_inlining_visitor::visit_enter(ir_assignment *ir) -{ - ir_call *call = ir->rhs->as_call(); - if (!call || !can_inline(call)) - return visit_continue; - - /* generates the parameter setup, function body, and returns the return - * value of the function - */ - ir_rvalue *rhs = call->generate_inline(ir); - assert(rhs); - - ir->rhs = rhs; - this->progress = true; - - return visit_continue; -} - /** - * Replaces references to the "sampler" variable with a clone of "deref." + * Replaces references to the "orig" variable with a clone of "repl." * - * From the spec, samplers can appear in the tree as function + * From the spec, opaque types can appear in the tree as function * (non-out) parameters and as the result of array indexing and * structure field selection. In our builtin implementation, they * also appear in the sampler field of an ir_tex instruction. */ -class ir_sampler_replacement_visitor : public ir_hierarchical_visitor { +class ir_variable_replacement_visitor : public ir_hierarchical_visitor { public: - ir_sampler_replacement_visitor(ir_variable *sampler, ir_dereference *deref) + ir_variable_replacement_visitor(ir_variable *orig, ir_dereference *repl) { - this->sampler = sampler; - this->deref = deref; + this->orig = orig; + this->repl = repl; } - virtual ~ir_sampler_replacement_visitor() + virtual ~ir_variable_replacement_visitor() { } @@ -346,21 +285,21 @@ public: void replace_deref(ir_dereference **deref); void replace_rvalue(ir_rvalue **rvalue); - ir_variable *sampler; - ir_dereference *deref; + ir_variable *orig; + ir_dereference *repl; }; void -ir_sampler_replacement_visitor::replace_deref(ir_dereference **deref) +ir_variable_replacement_visitor::replace_deref(ir_dereference **deref) { ir_dereference_variable *deref_var = (*deref)->as_dereference_variable(); - if (deref_var && deref_var->var == this->sampler) { - *deref = this->deref->clone(ralloc_parent(*deref), NULL); + if (deref_var && deref_var->var == this->orig) { + *deref = this->repl->clone(ralloc_parent(*deref), NULL); } } void -ir_sampler_replacement_visitor::replace_rvalue(ir_rvalue **rvalue) +ir_variable_replacement_visitor::replace_rvalue(ir_rvalue **rvalue) { if (!*rvalue) return; @@ -375,7 +314,7 @@ ir_sampler_replacement_visitor::replace_rvalue(ir_rvalue **rvalue) } ir_visitor_status -ir_sampler_replacement_visitor::visit_leave(ir_texture *ir) +ir_variable_replacement_visitor::visit_leave(ir_texture *ir) { replace_deref(&ir->sampler); @@ -383,24 +322,23 @@ ir_sampler_replacement_visitor::visit_leave(ir_texture *ir) } ir_visitor_status -ir_sampler_replacement_visitor::visit_leave(ir_dereference_array *ir) +ir_variable_replacement_visitor::visit_leave(ir_dereference_array *ir) { replace_rvalue(&ir->array); return visit_continue; } ir_visitor_status -ir_sampler_replacement_visitor::visit_leave(ir_dereference_record *ir) +ir_variable_replacement_visitor::visit_leave(ir_dereference_record *ir) { replace_rvalue(&ir->record); return visit_continue; } ir_visitor_status -ir_sampler_replacement_visitor::visit_leave(ir_call *ir) +ir_variable_replacement_visitor::visit_leave(ir_call *ir) { - foreach_iter(exec_list_iterator, iter, *ir) { - ir_rvalue *param = (ir_rvalue *)iter.get(); + foreach_in_list_safe(ir_rvalue, param, &ir->actual_parameters) { ir_rvalue *new_param = param; replace_rvalue(&new_param); @@ -412,11 +350,11 @@ ir_sampler_replacement_visitor::visit_leave(ir_call *ir) } static void -do_sampler_replacement(exec_list *instructions, - ir_variable *sampler, - ir_dereference *deref) +do_variable_replacement(exec_list *instructions, + ir_variable *orig, + ir_dereference *repl) { - ir_sampler_replacement_visitor v(sampler, deref); + ir_variable_replacement_visitor v(orig, repl); visit_list_elements(&v, instructions); }