summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/ast_function.cpp46
-rw-r--r--src/glsl/builtins/ir/acos.ir23
-rw-r--r--src/glsl/builtins/ir/atan.ir80
-rw-r--r--src/glsl/ir.cpp2
-rw-r--r--src/glsl/ir.h22
-rw-r--r--src/glsl/ir_basic_block.cpp43
-rw-r--r--src/glsl/ir_clone.cpp6
-rw-r--r--src/glsl/ir_constant_expression.cpp3
-rw-r--r--src/glsl/ir_expression_flattening.cpp5
-rw-r--r--src/glsl/ir_hv_accept.cpp8
-rw-r--r--src/glsl/ir_print_visitor.cpp5
-rw-r--r--src/glsl/ir_reader.cpp32
-rw-r--r--src/glsl/ir_validate.cpp11
-rw-r--r--src/glsl/linker.cpp10
-rw-r--r--src/glsl/opt_constant_folding.cpp10
-rw-r--r--src/glsl/opt_constant_variable.cpp12
-rw-r--r--src/glsl/opt_dead_code.cpp3
-rw-r--r--src/glsl/opt_dead_code_local.cpp7
-rw-r--r--src/glsl/opt_function_inlining.cpp62
-rw-r--r--src/glsl/opt_tree_grafting.cpp3
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, &parameters);
+ 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, &parameters);
}
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;
}