diff options
author | Eric Anholt <[email protected]> | 2010-06-23 11:37:12 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2010-06-23 15:20:29 -0700 |
commit | 4b6fd39c89f308a379882426c1ed3616d60c4628 (patch) | |
tree | 2c8f6f7e2e3eae5922a91c61a686457c614068fe /ir_function_inlining.cpp | |
parent | 02fc4b34e40f655eebc99f6502293b4d4000e0b3 (diff) |
Add a virtual clone() method to ir_instruction.
This will be used by function inlining, the linker, and avoiding double
usage of the LHS deref chains in ++, *=, and similar operations.
Diffstat (limited to 'ir_function_inlining.cpp')
-rw-r--r-- | ir_function_inlining.cpp | 293 |
1 files changed, 13 insertions, 280 deletions
diff --git a/ir_function_inlining.cpp b/ir_function_inlining.cpp index 4e5604f89fe..effb01c8f68 100644 --- a/ir_function_inlining.cpp +++ b/ir_function_inlining.cpp @@ -27,11 +27,13 @@ * Replaces calls to functions with the body of the function. */ +#include <inttypes.h> #include "ir.h" #include "ir_visitor.h" #include "ir_function_inlining.h" #include "ir_expression_flattening.h" #include "glsl_types.h" +#include "hash_table.h" class ir_function_inlining_visitor : public ir_hierarchical_visitor { public: @@ -55,283 +57,15 @@ public: bool progress; }; -class variable_remap : public exec_node { -public: - variable_remap(const ir_variable *old_var, ir_variable *new_var) - : old_var(old_var), new_var(new_var) - { - /* empty */ - } - const ir_variable *old_var; - ir_variable *new_var; -}; - -class ir_function_cloning_visitor : public ir_visitor { -public: - ir_function_cloning_visitor(ir_variable *retval) - : retval(retval) - { - /* empty */ - } - - virtual ~ir_function_cloning_visitor() - { - /* empty */ - } - - void remap_variable(const ir_variable *old_var, ir_variable *new_var) { - variable_remap *remap = new variable_remap(old_var, new_var); - this->remap_list.push_tail(remap); - } - - ir_variable *get_remapped_variable(ir_variable *var) { - foreach_iter(exec_list_iterator, iter, this->remap_list) { - variable_remap *remap = (variable_remap *)iter.get(); - - if (var == remap->old_var) - return remap->new_var; - } - - /* Not a reapped variable, so a global scoped reference, for example. */ - return var; - } - - /* List of variable_remap for mapping from original function body variables - * to inlined function body variables. - */ - exec_list remap_list; - - /* Return value for the inlined function. */ - ir_variable *retval; - - /** - * \name Visit methods - * - * As typical for the visitor pattern, there must be one \c visit method for - * each concrete subclass of \c ir_instruction. Virtual base classes within - * the hierarchy should not have \c visit methods. - */ - /*@{*/ - virtual void visit(ir_variable *); - virtual void visit(ir_loop *); - virtual void visit(ir_loop_jump *); - virtual void visit(ir_function_signature *); - virtual void visit(ir_function *); - virtual void visit(ir_expression *); - virtual void visit(ir_texture *); - virtual void visit(ir_swizzle *); - virtual void visit(ir_dereference_variable *); - virtual void visit(ir_dereference_array *); - virtual void visit(ir_dereference_record *); - virtual void visit(ir_assignment *); - virtual void visit(ir_constant *); - virtual void visit(ir_call *); - virtual void visit(ir_return *); - virtual void visit(ir_if *); - /*@}*/ - - ir_instruction *result; -}; - -void -ir_function_cloning_visitor::visit(ir_variable *ir) -{ - ir_variable *new_var = ir->clone(); - - this->result = new_var; - this->remap_variable(ir, new_var); -} - -void -ir_function_cloning_visitor::visit(ir_loop *ir) -{ - /* FINISHME: Implement loop cloning. */ - assert(0); - - (void)ir; - this->result = NULL; -} - -void -ir_function_cloning_visitor::visit(ir_loop_jump *ir) -{ - /* FINISHME: Implement loop cloning. */ - assert(0); - - (void) ir; - this->result = NULL; -} - - -void -ir_function_cloning_visitor::visit(ir_function_signature *ir) -{ - assert(0); - (void)ir; - this->result = NULL; -} - - -void -ir_function_cloning_visitor::visit(ir_function *ir) +unsigned int hash_func(const void *key) { - assert(0); - (void) ir; - this->result = NULL; + return (unsigned int)(uintptr_t)key; } -void -ir_function_cloning_visitor::visit(ir_expression *ir) +int hash_compare_func(const void *key1, const void *key2) { - unsigned int operand; - ir_rvalue *op[2] = {NULL, NULL}; - - for (operand = 0; operand < ir->get_num_operands(); operand++) { - ir->operands[operand]->accept(this); - op[operand] = this->result->as_rvalue(); - assert(op[operand]); - } - - this->result = new ir_expression(ir->operation, ir->type, op[0], op[1]); -} - - -void -ir_function_cloning_visitor::visit(ir_texture *ir) -{ - ir_texture *tex = new ir_texture(ir->op); - - ir->sampler->accept(this); - tex->set_sampler(this->result->as_dereference()); - - ir->coordinate->accept(this); - tex->coordinate = this->result->as_rvalue(); - - if (ir->projector != NULL) { - ir->projector->accept(this); - tex->projector = this->result->as_rvalue(); - } - - if (ir->shadow_comparitor != NULL) { - ir->shadow_comparitor->accept(this); - tex->shadow_comparitor = this->result->as_rvalue(); - } - - for (int i = 0; i < 3; i++) - tex->offsets[i] = ir->offsets[i]; - - tex->lod_info = ir->lod_info; -} - - -void -ir_function_cloning_visitor::visit(ir_swizzle *ir) -{ - ir->val->accept(this); - - this->result = new ir_swizzle(this->result->as_rvalue(), ir->mask); -} - -void -ir_function_cloning_visitor::visit(ir_dereference_variable *ir) -{ - ir_variable *var = this->get_remapped_variable(ir->variable_referenced()); - this->result = new ir_dereference_variable(var); -} - -void -ir_function_cloning_visitor::visit(ir_dereference_array *ir) -{ - ir->array->accept(this); - - ir_rvalue *var = this->result->as_rvalue(); - - ir->array_index->accept(this); - - ir_rvalue *index = this->result->as_rvalue(); - - this->result = new ir_dereference_array(var, index); -} - -void -ir_function_cloning_visitor::visit(ir_dereference_record *ir) -{ - ir->record->accept(this); - - ir_rvalue *var = this->result->as_rvalue(); - - this->result = new ir_dereference_record(var, strdup(ir->field)); -} - -void -ir_function_cloning_visitor::visit(ir_assignment *ir) -{ - ir_rvalue *lhs, *rhs, *condition = NULL; - - ir->lhs->accept(this); - lhs = this->result->as_rvalue(); - - ir->rhs->accept(this); - rhs = this->result->as_rvalue(); - - if (ir->condition) { - ir->condition->accept(this); - condition = this->result->as_rvalue(); - } - - this->result = new ir_assignment(lhs, rhs, condition); -} - - -void -ir_function_cloning_visitor::visit(ir_constant *ir) -{ - this->result = ir->clone(); -} - - -void -ir_function_cloning_visitor::visit(ir_call *ir) -{ - exec_list parameters; - - foreach_iter(exec_list_iterator, iter, *ir) { - ir_rvalue *param = (ir_rvalue *)iter.get(); - - param->accept(this); - parameters.push_tail(this->result); - } - - this->result = new ir_call(ir->get_callee(), ¶meters); -} - - -void -ir_function_cloning_visitor::visit(ir_return *ir) -{ - ir_rvalue *rval; - - assert(this->retval); - - rval = ir->get_value(); - rval->accept(this); - rval = this->result->as_rvalue(); - assert(rval); - - result = new ir_assignment(new ir_dereference_variable(this->retval), rval, - NULL); -} - - -void -ir_function_cloning_visitor::visit(ir_if *ir) -{ - /* FINISHME: Implement if cloning. */ - assert(0); - - (void) ir; - result = NULL; + return key1 == key2 ? 0 : 1; } bool @@ -364,6 +98,9 @@ ir_call::generate_inline(ir_instruction *next_ir) int num_parameters; int i; ir_variable *retval = NULL; + struct hash_table *ht; + + ht = hash_table_ctor(0, hash_func, hash_compare_func); num_parameters = 0; foreach_iter(exec_list_iterator, iter_sig, this->callee->parameters) @@ -377,8 +114,6 @@ ir_call::generate_inline(ir_instruction *next_ir) next_ir->insert_before(retval); } - ir_function_cloning_visitor v = ir_function_cloning_visitor(retval); - /* Generate the declarations for the parameters to our inlined code, * and set up the mapping of real function body variables to ours. */ @@ -390,11 +125,9 @@ ir_call::generate_inline(ir_instruction *next_ir) ir_rvalue *param = (ir_rvalue *) param_iter.get(); /* Generate a new variable for the parameter. */ - parameters[i] = sig_param->clone(); + parameters[i] = (ir_variable *)sig_param->clone(ht); next_ir->insert_before(parameters[i]); - v.remap_variable(sig_param, parameters[i]); - /* Move the actual param into our param variable if it's an 'in' type. */ if (parameters[i]->mode == ir_var_in || parameters[i]->mode == ir_var_inout) { @@ -413,9 +146,7 @@ ir_call::generate_inline(ir_instruction *next_ir) foreach_iter(exec_list_iterator, iter, callee->body) { ir_instruction *ir = (ir_instruction *)iter.get(); - ir->accept(&v); - assert(v.result); - next_ir->insert_before(v.result); + next_ir->insert_before(ir->clone(ht)); } /* Copy back the value of any 'out' parameters from the function body @@ -442,6 +173,8 @@ ir_call::generate_inline(ir_instruction *next_ir) delete [] parameters; + hash_table_dtor(ht); + if (retval) return new ir_dereference_variable(retval); else |