summaryrefslogtreecommitdiffstats
path: root/ir_function_inlining.cpp
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2010-06-23 11:37:12 -0700
committerIan Romanick <[email protected]>2010-06-23 15:20:29 -0700
commit4b6fd39c89f308a379882426c1ed3616d60c4628 (patch)
tree2c8f6f7e2e3eae5922a91c61a686457c614068fe /ir_function_inlining.cpp
parent02fc4b34e40f655eebc99f6502293b4d4000e0b3 (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.cpp293
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(), &parameters);
-}
-
-
-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