diff options
-rw-r--r-- | src/glsl/ast_function.cpp | 46 | ||||
-rw-r--r-- | src/glsl/builtins/ir/acos.ir | 23 | ||||
-rw-r--r-- | src/glsl/builtins/ir/atan.ir | 80 | ||||
-rw-r--r-- | src/glsl/ir.cpp | 2 | ||||
-rw-r--r-- | src/glsl/ir.h | 22 | ||||
-rw-r--r-- | src/glsl/ir_basic_block.cpp | 43 | ||||
-rw-r--r-- | src/glsl/ir_clone.cpp | 6 | ||||
-rw-r--r-- | src/glsl/ir_constant_expression.cpp | 3 | ||||
-rw-r--r-- | src/glsl/ir_expression_flattening.cpp | 5 | ||||
-rw-r--r-- | src/glsl/ir_hv_accept.cpp | 8 | ||||
-rw-r--r-- | src/glsl/ir_print_visitor.cpp | 5 | ||||
-rw-r--r-- | src/glsl/ir_reader.cpp | 32 | ||||
-rw-r--r-- | src/glsl/ir_validate.cpp | 11 | ||||
-rw-r--r-- | src/glsl/linker.cpp | 10 | ||||
-rw-r--r-- | src/glsl/opt_constant_folding.cpp | 10 | ||||
-rw-r--r-- | src/glsl/opt_constant_variable.cpp | 12 | ||||
-rw-r--r-- | src/glsl/opt_dead_code.cpp | 3 | ||||
-rw-r--r-- | src/glsl/opt_dead_code_local.cpp | 7 | ||||
-rw-r--r-- | src/glsl/opt_function_inlining.cpp | 62 | ||||
-rw-r--r-- | src/glsl/opt_tree_grafting.cpp | 3 |
20 files changed, 185 insertions, 208 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index 934bc5e891a..dfdbc55c575 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -269,29 +269,21 @@ generate_call(exec_list *instructions, ir_function_signature *sig, formal_iter.next(); } - /* Always insert the call in the instruction stream, and return a deref - * of its return val if it returns a value, since we don't know if - * the rvalue is going to be assigned to anything or not. + /* If the function call is a constant expression, don't generate any + * instructions; just generate an ir_constant. * - * Also insert any out parameter conversions after the call. + * Function calls were first allowed to be constant expressions in GLSL 1.20. */ - ir_call *call = new(ctx) ir_call(sig, actual_parameters); - ir_dereference_variable *deref; - if (!sig->return_type->is_void()) { - /* If the function call is a constant expression, don't - * generate the instructions to call it; just generate an - * ir_constant representing the constant value. - * - * Function calls can only be constant expressions starting - * in GLSL 1.20. - */ - if (state->language_version >= 120) { - ir_constant *const_val = call->constant_expression_value(); - if (const_val) { - return const_val; - } + if (state->language_version >= 120) { + ir_constant *value = sig->constant_expression_value(actual_parameters); + if (value != NULL) { + return value; } + } + ir_dereference_variable *deref = NULL; + if (!sig->return_type->is_void()) { + /* Create a new temporary to hold the return value. */ ir_variable *var; var = new(ctx) ir_variable(sig->return_type, @@ -301,18 +293,14 @@ generate_call(exec_list *instructions, ir_function_signature *sig, instructions->push_tail(var); deref = new(ctx) ir_dereference_variable(var); - ir_assignment *assign = new(ctx) ir_assignment(deref, call, NULL); - instructions->push_tail(assign); - *call_ir = call; - - deref = new(ctx) ir_dereference_variable(var); - } else { - instructions->push_tail(call); - *call_ir = call; - deref = NULL; } + ir_call *call = new(ctx) ir_call(sig, deref, actual_parameters); + instructions->push_tail(call); + + /* Also emit any necessary out-parameter conversions. */ instructions->append_list(&post_call_conversions); - return deref; + + return deref ? deref->clone(ctx, NULL) : NULL; } /** diff --git a/src/glsl/builtins/ir/acos.ir b/src/glsl/builtins/ir/acos.ir index d1cfebeff8a..f0078f884e7 100644 --- a/src/glsl/builtins/ir/acos.ir +++ b/src/glsl/builtins/ir/acos.ir @@ -2,21 +2,28 @@ (signature float (parameters (declare (in) float x)) - ((return (expression float - (constant float (1.5707963)) - (call asin ((var_ref x))))))) + ((declare () float s) + (call asin (var_ref s) ((var_ref x))) + (return (expression float - (constant float (1.5707963)) (var_ref s))))) + (signature vec2 (parameters (declare (in) vec2 x)) - ((return (expression vec2 - (constant float (1.5707963)) - (call asin ((var_ref x))))))) + ((declare () vec2 s) + (call asin (var_ref s) ((var_ref x))) + (return (expression vec2 - (constant float (1.5707963)) (var_ref s))))) + (signature vec3 (parameters (declare (in) vec3 x)) - ((return (expression vec3 - (constant float (1.5707963)) - (call asin ((var_ref x))))))) + ((declare () vec3 s) + (call asin (var_ref s) ((var_ref x))) + (return (expression vec3 - (constant float (1.5707963)) (var_ref s))))) + (signature vec4 (parameters (declare (in) vec4 x)) - ((return (expression vec4 - (constant float (1.5707963)) - (call asin ((var_ref x))))))) + ((declare () vec4 s) + (call asin (var_ref s) ((var_ref x))) + (return (expression vec4 - (constant float (1.5707963)) (var_ref s))))) )) diff --git a/src/glsl/builtins/ir/atan.ir b/src/glsl/builtins/ir/atan.ir index 7b5ea13c6ba..a9dc08e9727 100644 --- a/src/glsl/builtins/ir/atan.ir +++ b/src/glsl/builtins/ir/atan.ir @@ -2,50 +2,62 @@ (signature float (parameters (declare (in) float y_over_x)) - ((return (call asin ((expression float * + ((declare () float s) + (call asin (var_ref s) + ((expression float * (var_ref y_over_x) (expression float rsq (expression float + (expression float * (var_ref y_over_x) (var_ref y_over_x)) - (constant float (1.0)))))))))) + (constant float (1.0))))))) + (return (var_ref s)))) (signature vec2 (parameters (declare (in) vec2 y_over_x)) - ((return (call asin ((expression vec2 * + ((declare () vec2 s) + (call asin (var_ref s) + ((expression vec2 * (var_ref y_over_x) (expression vec2 rsq (expression vec2 + (expression vec2 * (var_ref y_over_x) (var_ref y_over_x)) - (constant float (1.0)))))))))) + (constant float (1.0))))))) + (return (var_ref s)))) (signature vec3 (parameters (declare (in) vec3 y_over_x)) - ((return (call asin ((expression vec3 * + ((declare () vec3 s) + (call asin (var_ref s) + ((expression vec3 * (var_ref y_over_x) (expression vec3 rsq (expression vec3 + (expression vec3 * (var_ref y_over_x) (var_ref y_over_x)) - (constant float (1.0)))))))))) + (constant float (1.0))))))) + (return (var_ref s)))) (signature vec4 (parameters (declare (in) vec4 y_over_x)) - ((return (call asin ((expression vec4 * + ((declare () vec4 s) + (call asin (var_ref s) + ((expression vec4 * (var_ref y_over_x) (expression vec4 rsq (expression vec4 + (expression vec4 * (var_ref y_over_x) (var_ref y_over_x)) - (constant float (1.0)))))))))) + (constant float (1.0))))))) + (return (var_ref s)))) (signature float (parameters @@ -57,7 +69,7 @@ (if (expression bool > (expression float abs (var_ref x)) (expression float * (constant float (1.0e-8)) (expression float abs (var_ref y)))) ( - (assign (x) (var_ref r) (call atan ((expression float / (var_ref y) (var_ref x))))) + (call atan (var_ref r) ((expression float / (var_ref y) (var_ref x)))) (if (expression bool < (var_ref x) (constant float (0.000000)) ) ( (if (expression bool >= (var_ref y) (constant float (0.000000)) ) ((assign (x) (var_ref r) (expression float + (var_ref r) (constant float (3.141593))))) @@ -82,12 +94,11 @@ (declare (in) vec2 y) (declare (in) vec2 x)) ((declare () vec2 r) - (assign (x) (var_ref r) - (call atan ((swiz x (var_ref y)) - (swiz x (var_ref x))))) - (assign (y) (var_ref r) - (call atan ((swiz y (var_ref y)) - (swiz y (var_ref x))))) + (declare () float temp) + (call atan (var_ref temp) ((swiz x (var_ref y)) (swiz x (var_ref x)))) + (assign (x) (var_ref r) (var_ref temp)) + (call atan (var_ref temp) ((swiz y (var_ref y)) (swiz y (var_ref x)))) + (assign (y) (var_ref r) (var_ref temp)) (return (var_ref r)))) (signature vec3 @@ -95,15 +106,13 @@ (declare (in) vec3 y) (declare (in) vec3 x)) ((declare () vec3 r) - (assign (x) (var_ref r) - (call atan ((swiz x (var_ref y)) - (swiz x (var_ref x))))) - (assign (y) (var_ref r) - (call atan ((swiz y (var_ref y)) - (swiz y (var_ref x))))) - (assign (z) (var_ref r) - (call atan ((swiz z (var_ref y)) - (swiz z (var_ref x))))) + (declare () float temp) + (call atan (var_ref temp) ((swiz x (var_ref y)) (swiz x (var_ref x)))) + (assign (x) (var_ref r) (var_ref temp)) + (call atan (var_ref temp) ((swiz y (var_ref y)) (swiz y (var_ref x)))) + (assign (y) (var_ref r) (var_ref temp)) + (call atan (var_ref temp) ((swiz z (var_ref y)) (swiz z (var_ref x)))) + (assign (z) (var_ref r) (var_ref temp)) (return (var_ref r)))) (signature vec4 @@ -111,18 +120,15 @@ (declare (in) vec4 y) (declare (in) vec4 x)) ((declare () vec4 r) - (assign (x) (var_ref r) - (call atan ((swiz x (var_ref y)) - (swiz x (var_ref x))))) - (assign (y) (var_ref r) - (call atan ((swiz y (var_ref y)) - (swiz y (var_ref x))))) - (assign (z) (var_ref r) - (call atan ((swiz z (var_ref y)) - (swiz z (var_ref x))))) - (assign (w) (var_ref r) - (call atan ((swiz w (var_ref y)) - (swiz w (var_ref x))))) - (return (var_ref r))))) + (declare () float temp) + (call atan (var_ref temp) ((swiz x (var_ref y)) (swiz x (var_ref x)))) + (assign (x) (var_ref r) (var_ref temp)) + (call atan (var_ref temp) ((swiz y (var_ref y)) (swiz y (var_ref x)))) + (assign (y) (var_ref r) (var_ref temp)) + (call atan (var_ref temp) ((swiz z (var_ref y)) (swiz z (var_ref x)))) + (assign (z) (var_ref r) (var_ref temp)) + (call atan (var_ref temp) ((swiz w (var_ref y)) (swiz w (var_ref x)))) + (assign (w) (var_ref r) (var_ref temp)) + (return (var_ref r)))) )) diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index b497ff154ba..3595e742f78 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -1470,8 +1470,6 @@ ir_rvalue::error_value(void *mem_ctx) void ir_call::set_callee(ir_function_signature *sig) { - assert((this->type == NULL) || (this->type == sig->return_type)); - this->callee = sig; } diff --git a/src/glsl/ir.h b/src/glsl/ir.h index bb4f7759b30..054e2acaadb 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -1023,16 +1023,18 @@ public: /** - * IR instruction representing a function call + * HIR instruction representing a high-level function call, containing a list + * of parameters and returning a value in the supplied temporary. */ -class ir_call : public ir_rvalue { +class ir_call : public ir_instruction { public: - ir_call(ir_function_signature *callee, exec_list *actual_parameters) - : callee(callee) + ir_call(ir_function_signature *callee, + ir_dereference_variable *return_deref, + exec_list *actual_parameters) + : return_deref(return_deref), callee(callee) { ir_type = ir_type_call; assert(callee->return_type != NULL); - type = callee->return_type; actual_parameters->move_nodes_to(& this->actual_parameters); this->use_builtin = callee->is_builtin; } @@ -1084,9 +1086,15 @@ public: /** * Generates an inline version of the function before @ir, - * returning the return value of the function. + * storing the return value in return_deref. */ - ir_rvalue *generate_inline(ir_instruction *ir); + void generate_inline(ir_instruction *ir); + + /** + * Storage for the function's return value. + * This must be NULL if the return type is void. + */ + ir_dereference_variable *return_deref; /* List of ir_rvalue of paramaters passed in this call. */ exec_list actual_parameters; diff --git a/src/glsl/ir_basic_block.cpp b/src/glsl/ir_basic_block.cpp index a8338259620..86e0cf795a1 100644 --- a/src/glsl/ir_basic_block.cpp +++ b/src/glsl/ir_basic_block.cpp @@ -32,31 +32,6 @@ #include "ir_basic_block.h" #include "glsl_types.h" -class ir_has_call_visitor : public ir_hierarchical_visitor { -public: - ir_has_call_visitor() - { - has_call = false; - } - - virtual ir_visitor_status visit_enter(ir_call *ir) - { - (void) ir; - has_call = true; - return visit_stop; - } - - bool has_call; -}; - -bool -ir_has_call(ir_instruction *ir) -{ - ir_has_call_visitor v; - ir->accept(&v); - return v.has_call; -} - /** * Calls a user function for every basic block in the instruction stream. * @@ -122,24 +97,6 @@ void call_for_basic_blocks(exec_list *instructions, call_for_basic_blocks(&ir_sig->body, callback, data); } - } else if (ir->as_assignment()) { - /* If there's a call in the expression tree being assigned, - * then that ends the BB too. - * - * The assumption is that any consumer of the basic block - * walker is fine with the fact that the call is somewhere in - * the tree even if portions of the tree may be evaluated - * after the call. - * - * A consumer that has an issue with this could not process - * the last instruction of the basic block. If doing so, - * expression flattener may be useful before using the basic - * block finder to get more maximal basic blocks out. - */ - if (ir_has_call(ir)) { - callback(leader, ir, data); - leader = NULL; - } } last = ir; } diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index b6d0e8aa4a3..8a9701c9496 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -167,6 +167,10 @@ ir_loop::clone(void *mem_ctx, struct hash_table *ht) const ir_call * ir_call::clone(void *mem_ctx, struct hash_table *ht) const { + ir_dereference_variable *new_return_ref = NULL; + if (this->return_deref != NULL) + new_return_ref = this->return_deref->clone(mem_ctx, ht); + exec_list new_parameters; foreach_iter(exec_list_iterator, iter, this->actual_parameters) { @@ -174,7 +178,7 @@ ir_call::clone(void *mem_ctx, struct hash_table *ht) const new_parameters.push_tail(ir->clone(mem_ctx, ht)); } - return new(mem_ctx) ir_call(this->callee, &new_parameters); + return new(mem_ctx) ir_call(this->callee, new_return_ref, &new_parameters); } ir_expression * diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index aa47c08d88a..4e1714a8420 100644 --- a/src/glsl/ir_constant_expression.cpp +++ b/src/glsl/ir_constant_expression.cpp @@ -1024,9 +1024,6 @@ ir_constant::constant_expression_value() ir_constant * ir_call::constant_expression_value() { - if (this->type == glsl_type::error_type) - return NULL; - return this->callee->constant_expression_value(&this->actual_parameters); } diff --git a/src/glsl/ir_expression_flattening.cpp b/src/glsl/ir_expression_flattening.cpp index bd4ac67bc1a..b44e68ca364 100644 --- a/src/glsl/ir_expression_flattening.cpp +++ b/src/glsl/ir_expression_flattening.cpp @@ -29,11 +29,6 @@ * * This is used for breaking down matrix operations, where it's easier to * create a temporary and work on each of its vector components individually. - * - * It is also used for automatic function inlining, where we want to take - * an expression containing a call and move the call out to its own - * assignment so that we can inline it at the appropriate place in the - * instruction stream. */ #include "ir.h" diff --git a/src/glsl/ir_hv_accept.cpp b/src/glsl/ir_hv_accept.cpp index c3be0521598..3ce8959245d 100644 --- a/src/glsl/ir_hv_accept.cpp +++ b/src/glsl/ir_hv_accept.cpp @@ -333,6 +333,14 @@ ir_call::accept(ir_hierarchical_visitor *v) if (s != visit_continue) return (s == visit_continue_with_parent) ? visit_continue : s; + if (this->return_deref != NULL) { + v->in_assignee = true; + s = this->return_deref->accept(v); + v->in_assignee = false; + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + } + s = visit_list_elements(v, &this->actual_parameters, false); if (s == visit_stop) return s; diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp index 78ba0ba9c81..8aa26e5d018 100644 --- a/src/glsl/ir_print_visitor.cpp +++ b/src/glsl/ir_print_visitor.cpp @@ -408,7 +408,10 @@ void ir_print_visitor::visit(ir_constant *ir) void ir_print_visitor::visit(ir_call *ir) { - printf("(call %s (", ir->callee_name()); + printf("(call %s ", ir->callee_name()); + if (ir->return_deref) + ir->return_deref->accept(this); + printf(" ("); foreach_iter(exec_list_iterator, iter, *ir) { ir_instruction *const inst = (ir_instruction *) iter.get(); diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp index e66ae470438..7ce683ef7d3 100644 --- a/src/glsl/ir_reader.cpp +++ b/src/glsl/ir_reader.cpp @@ -51,11 +51,11 @@ private: ir_variable *read_declaration(s_expression *); ir_if *read_if(s_expression *, ir_loop *); ir_loop *read_loop(s_expression *); + ir_call *read_call(s_expression *); ir_return *read_return(s_expression *); ir_rvalue *read_rvalue(s_expression *); ir_assignment *read_assignment(s_expression *); ir_expression *read_expression(s_expression *); - ir_call *read_call(s_expression *); ir_swizzle *read_swizzle(s_expression *); ir_constant *read_constant(s_expression *); ir_texture *read_texture(s_expression *); @@ -349,6 +349,8 @@ ir_reader::read_instruction(s_expression *expr, ir_loop *loop_ctx) inst = read_if(list, loop_ctx); } else if (strcmp(tag->value(), "loop") == 0) { inst = read_loop(list); + } else if (strcmp(tag->value(), "call") == 0) { + inst = read_call(list); } else if (strcmp(tag->value(), "return") == 0) { inst = read_return(list); } else if (strcmp(tag->value(), "function") == 0) { @@ -522,8 +524,6 @@ ir_reader::read_rvalue(s_expression *expr) rvalue = read_swizzle(list); } else if (strcmp(tag->value(), "expression") == 0) { rvalue = read_expression(list); - } else if (strcmp(tag->value(), "call") == 0) { - rvalue = read_call(list); } else if (strcmp(tag->value(), "constant") == 0) { rvalue = read_constant(list); } else { @@ -611,10 +611,20 @@ ir_reader::read_call(s_expression *expr) { s_symbol *name; s_list *params; + s_list *s_return = NULL; - s_pattern pat[] = { "call", name, params }; - if (!MATCH(expr, pat)) { - ir_read_error(expr, "expected (call <name> (<param> ...))"); + ir_dereference_variable *return_deref = NULL; + + s_pattern void_pat[] = { "call", name, params }; + s_pattern non_void_pat[] = { "call", name, s_return, params }; + if (MATCH(expr, non_void_pat)) { + return_deref = read_var_ref(s_return); + if (return_deref == NULL) { + ir_read_error(s_return, "when reading a call's return storage"); + return NULL; + } + } else if (!MATCH(expr, void_pat)) { + ir_read_error(expr, "expected (call <name> [<deref>] (<param> ...))"); return NULL; } @@ -644,7 +654,15 @@ ir_reader::read_call(s_expression *expr) return NULL; } - return new(mem_ctx) ir_call(callee, ¶meters); + if (callee->return_type == glsl_type::void_type && return_deref) { + ir_read_error(expr, "call has return value storage but void type"); + return NULL; + } else if (callee->return_type != glsl_type::void_type && !return_deref) { + ir_read_error(expr, "call has non-void type but no return value storage"); + return NULL; + } + + return new(mem_ctx) ir_call(callee, return_deref, ¶meters); } ir_expression * diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp index 101d9992da2..66dd84f73f3 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -548,6 +548,17 @@ ir_validate::visit_enter(ir_call *ir) abort(); } + if (ir->return_deref) { + if (ir->return_deref->type != callee->return_type) { + printf("callee type %s does not match return storage type %s\n", + callee->return_type->name, ir->return_deref->type->name); + abort(); + } + } else if (callee->return_type != glsl_type::void_type) { + printf("ir_call has non-void callee but no return storage\n"); + abort(); + } + const exec_node *formal_param_node = callee->parameters.head; const exec_node *actual_param_node = ir->actual_parameters.head; while (true) { diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 09ffdff63fb..d56eb97e45a 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -117,6 +117,15 @@ public: sig_iter.next(); } + if (ir->return_deref != NULL) { + ir_variable *const var = ir->return_deref->variable_referenced(); + + if (strcmp(name, var->name) == 0) { + found = true; + return visit_stop; + } + } + return visit_continue_with_parent; } @@ -830,6 +839,7 @@ move_non_declarations(exec_list *instructions, exec_node *last, continue; assert(inst->as_assignment() + || inst->as_call() || ((var != NULL) && (var->mode == ir_var_temporary))); if (make_copies) { diff --git a/src/glsl/opt_constant_folding.cpp b/src/glsl/opt_constant_folding.cpp index 599b21525de..db8cd5cee6d 100644 --- a/src/glsl/opt_constant_folding.cpp +++ b/src/glsl/opt_constant_folding.cpp @@ -117,6 +117,7 @@ ir_constant_folding_visitor::visit_enter(ir_assignment *ir) ir_visitor_status ir_constant_folding_visitor::visit_enter(ir_call *ir) { + /* Attempt to constant fold parameters */ exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator(); foreach_iter(exec_list_iterator, iter, *ir) { ir_rvalue *param_rval = (ir_rvalue *)iter.get(); @@ -133,6 +134,15 @@ ir_constant_folding_visitor::visit_enter(ir_call *ir) sig_iter.next(); } + /* Next, see if the call can be replaced with an assignment of a constant */ + ir_constant *const_val = ir->constant_expression_value(); + + if (const_val != NULL) { + ir_assignment *assignment = + new(ralloc_parent(ir)) ir_assignment(ir->return_deref, const_val); + ir->replace_with(assignment); + } + return visit_continue_with_parent; } diff --git a/src/glsl/opt_constant_variable.cpp b/src/glsl/opt_constant_variable.cpp index 3fa7c3badc8..18c28018234 100644 --- a/src/glsl/opt_constant_variable.cpp +++ b/src/glsl/opt_constant_variable.cpp @@ -127,6 +127,7 @@ ir_constant_variable_visitor::visit_enter(ir_assignment *ir) ir_visitor_status ir_constant_variable_visitor::visit_enter(ir_call *ir) { + /* Mark any out parameters as assigned to */ exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator(); foreach_iter(exec_list_iterator, iter, *ir) { ir_rvalue *param_rval = (ir_rvalue *)iter.get(); @@ -143,6 +144,17 @@ ir_constant_variable_visitor::visit_enter(ir_call *ir) } sig_iter.next(); } + + /* Mark the return storage as having been assigned to */ + if (ir->return_deref != NULL) { + ir_variable *var = ir->return_deref->variable_referenced(); + struct assignment_entry *entry; + + assert(var); + entry = get_assignment_entry(var, &this->list); + entry->assignment_count++; + } + return visit_continue; } diff --git a/src/glsl/opt_dead_code.cpp b/src/glsl/opt_dead_code.cpp index 22c7af1c20a..0578f1737b0 100644 --- a/src/glsl/opt_dead_code.cpp +++ b/src/glsl/opt_dead_code.cpp @@ -78,8 +78,7 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned) * Don't do so if it's a shader output, though. */ if (entry->var->mode != ir_var_out && - entry->var->mode != ir_var_inout && - !ir_has_call(entry->assign)) { + entry->var->mode != ir_var_inout) { entry->assign->remove(); progress = true; diff --git a/src/glsl/opt_dead_code_local.cpp b/src/glsl/opt_dead_code_local.cpp index 39962bd602e..a81a38fff0f 100644 --- a/src/glsl/opt_dead_code_local.cpp +++ b/src/glsl/opt_dead_code_local.cpp @@ -149,12 +149,7 @@ process_assignment(void *ctx, ir_assignment *ir, exec_list *assignments) } } - /* Add this instruction to the assignment list available to be removed. - * But not if the assignment has other side effects. - */ - if (ir_has_call(ir)) - return progress; - + /* Add this instruction to the assignment list available to be removed. */ assignment_entry *entry = new(ctx) assignment_entry(var, ir); assignments->push_tail(entry); diff --git a/src/glsl/opt_function_inlining.cpp b/src/glsl/opt_function_inlining.cpp index ec8b72c632f..4ff4d97d9bc 100644 --- a/src/glsl/opt_function_inlining.cpp +++ b/src/glsl/opt_function_inlining.cpp @@ -53,7 +53,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 *); @@ -63,23 +62,10 @@ public: bool -automatic_inlining_predicate(ir_instruction *ir) -{ - ir_call *call = ir->as_call(); - - if (call && can_inline(call)) - return true; - - return false; -} - -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; @@ -89,12 +75,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 @@ -106,14 +92,13 @@ 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; int i; - ir_variable *retval = NULL; struct hash_table *ht; ht = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare); @@ -124,13 +109,6 @@ ir_call::generate_inline(ir_instruction *next_ir) 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. */ @@ -185,7 +163,7 @@ ir_call::generate_inline(ir_instruction *next_ir) 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 @@ -238,11 +216,6 @@ ir_call::generate_inline(ir_instruction *next_ir) delete [] parameters; hash_table_dtor(ht); - - if (retval) - return new(ctx) ir_dereference_variable(retval); - else - return NULL; } @@ -282,13 +255,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; } @@ -297,25 +264,6 @@ 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." * diff --git a/src/glsl/opt_tree_grafting.cpp b/src/glsl/opt_tree_grafting.cpp index e2aff5f8071..e70a2240fca 100644 --- a/src/glsl/opt_tree_grafting.cpp +++ b/src/glsl/opt_tree_grafting.cpp @@ -222,6 +222,9 @@ ir_tree_grafting_visitor::visit_enter(ir_call *ir) sig_iter.next(); } + if (ir->return_deref && check_graft(ir, ir->return_deref->var) == visit_stop) + return visit_stop; + return visit_continue; } |