[Mesa-dev] [PATCH] Starting work on var packer
Vincent Lejeune
vljn at ovi.com
Sun Aug 7 12:49:37 PDT 2011
From: vlj <vljn at ovi.com>
---
src/glsl/Makefile | 1 +
src/glsl/glsl_parser_extras.cpp | 7 +-
src/glsl/ir_optimization.h | 1 +
src/glsl/opt_var_packer.cpp | 332 +++++++++++++++++++++++++++++++++++++++
4 files changed, 338 insertions(+), 3 deletions(-)
create mode 100644 src/glsl/opt_var_packer.cpp
diff --git a/src/glsl/Makefile b/src/glsl/Makefile
index 68b98b2..226acc4 100644
--- a/src/glsl/Makefile
+++ b/src/glsl/Makefile
@@ -84,6 +84,7 @@ CXX_SOURCES = \
opt_swizzle_swizzle.cpp \
opt_tree_grafting.cpp \
opt_common_subexpression_elimination.cpp \
+ opt_var_packer.cpp \
s_expression.cpp
LIBS = \
diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
index 0a57386..1aa7d88 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -777,8 +777,9 @@ do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iteration
GLboolean progress = GL_FALSE;
- progress = do_common_subexpression_elimination(ir) || progress;
- /*progress = lower_instructions(ir, SUB_TO_ADD_NEG) || progress;
+ progress = do_var_packing (ir) || progress;
+ //progress = do_common_subexpression_elimination(ir) || progress;
+ progress = lower_instructions(ir, SUB_TO_ADD_NEG) || progress;
if (linked) {
progress = do_function_inlining(ir) || progress;
@@ -815,7 +816,7 @@ do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iteration
progress = set_loop_controls(ir, ls) || progress;
progress = unroll_loops(ir, ls, max_unroll_iterations) || progress;
}
- delete ls;*/
+ delete ls;
return progress;
}
diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h
index 3604e4e..5b1de66 100644
--- a/src/glsl/ir_optimization.h
+++ b/src/glsl/ir_optimization.h
@@ -72,3 +72,4 @@ bool lower_variable_index_to_cond_assign(exec_list *instructions,
bool lower_quadop_vector(exec_list *instructions, bool dont_lower_swz);
bool optimize_redundant_jumps(exec_list *instructions);
bool do_common_subexpression_elimination(exec_list *instructions);
+bool do_var_packing(exec_list *instructions);
diff --git a/src/glsl/opt_var_packer.cpp b/src/glsl/opt_var_packer.cpp
new file mode 100644
index 0000000..fe579f9
--- /dev/null
+++ b/src/glsl/opt_var_packer.cpp
@@ -0,0 +1,332 @@
+/*
+ * Copyright © 2011 Vincent Lejeune
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "ir.h"
+#include "ir_hierarchical_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include <cstring>
+
+class box : public exec_node
+{
+public:
+ void* content;
+ box(void* c):content(c)
+ {
+
+ }
+};
+
+
+
+class boxed_exec_list : public exec_list
+{
+public:
+ void push_tail(void *n)
+ {
+ box* b = new (this) box(n);
+ exec_list::push_tail(b);
+ }
+
+ void push_head(void *n)
+ {
+ box* b = new (this) box(n);
+ exec_list::push_head(b);
+ }
+
+ static void* operator new(size_t size, void *ctx)
+ {
+ void *node;
+
+ node = ralloc_size(ctx, size);
+ assert(node != NULL);
+
+ return node;
+ }
+
+ bool has(const void* pointer) const
+ {
+ foreach_list_const(tmp,this)
+ {
+ box* tmpb = reinterpret_cast<box*>(const_cast<exec_node*>(tmp));
+ if(tmpb->content == pointer)
+ return true;
+ }
+ return false;
+ }
+
+ int size()
+ {
+ int result=0;
+ foreach_list_const(tmp,this)
+ {
+ result++;
+ }
+ return result;
+ }
+};
+
+#define list_item(type,pointer) reinterpret_cast<type>(reinterpret_cast<box*>(pointer)->content)
+#define list_item_const(type,pointer) reinterpret_cast<type>(reinterpret_cast<box*>(const_cast<exec_node*>(pointer))->content)
+
+
+#include <iostream>
+using namespace std;
+
+class ir_variable_lister : public ir_hierarchical_visitor
+{
+ friend class ir_packer;
+protected:
+ boxed_exec_list* available_vec3;
+ boxed_exec_list* available_vec2;
+ boxed_exec_list* available_float;
+
+ void store_variable(ir_variable* var)
+ {
+ if(strcmp(var->name,"_ret_val") == 0)
+ return ;
+ switch(var->type->gl_type)
+ {
+ case GL_FLOAT_VEC3:
+ if(available_vec3->has(var)) break;
+ available_vec3->push_tail(var);
+ break;
+ case GL_FLOAT_VEC2:
+ if(available_vec2->has(var)) break;
+ available_vec2->push_tail(var);
+ break;
+ case GL_FLOAT:
+ if(available_float->has(var)) break;
+ available_float->push_tail(var);
+ break;
+ default:
+ break;
+ }
+ }
+
+ bool find_candidates(ir_variable*& var1,ir_swizzle_mask& mask1, ir_variable*& var2, ir_swizzle_mask& mask2)
+ {
+ if(available_vec3->size() > 1 && available_float->size() >1)
+ {
+ var1 = list_item(ir_variable*,available_vec3->pop_head());
+ var2 = list_item(ir_variable*,available_float->pop_head());
+ mask1.x = 0;mask1.y = 1;mask1.z = 2;mask1.num_components = 3;mask1.has_duplicates=false;
+ mask2.x = 3;mask2.num_components = 1;mask1.has_duplicates=false;
+ return true;
+ }
+ if(available_vec2->size() > 2)
+ {
+ var1 = list_item_const(ir_variable*,available_vec2->pop_head());
+ var2 = list_item_const(ir_variable*,available_vec2->pop_head());
+ mask1.x = 0;mask1.y = 1;mask1.num_components = 2;
+ mask2.x = 2; mask2.y = 3;mask2.num_components = 2;
+ return true;
+ }
+ if(available_vec2->size() > 1 && available_float->size() > 1)
+ {
+ var1 = list_item_const(ir_variable*,available_vec2->pop_head());
+ var2 = list_item_const(ir_variable*,available_float->pop_head());
+ mask1.x = 0;mask1.y = 1;mask1.num_components = 2;
+ mask2.x = 2; mask2.num_components = 1;
+ return true;
+ }
+ if(available_float->size() > 2)
+ {
+ var1 = list_item_const(ir_variable*,available_float->pop_head());
+ var2 = list_item_const(ir_variable*,available_float->pop_head());
+ mask1.x = 0;mask1.num_components = 1;
+ mask2.x = 1;mask2.num_components = 1;
+ return true;
+ }
+ return false;
+ }
+
+public:
+ ir_visitor_status visit(ir_dereference_variable * dref)
+ {
+ if(dref->var->mode != ir_var_auto)
+ return visit_continue;
+ store_variable(dref->var);
+ return visit_continue;
+ }
+
+ ir_variable_lister(void* ctx)
+ {
+ available_float = new (ctx) boxed_exec_list();
+ available_vec2 = new (ctx) boxed_exec_list();
+ available_vec3 = new (ctx) boxed_exec_list();
+ }
+
+};
+
+class ir_variable_replacer : public ir_rvalue_visitor
+{
+protected:
+ ir_variable* var1;
+ ir_swizzle_mask mask_for_var1;
+ ir_variable* var2;
+ ir_swizzle_mask mask_for_var2;
+ ir_variable* packed_var;
+
+ unsigned from_component(unsigned x) const
+ {
+ switch(x)
+ {
+ case 3:
+ return 1 << 3;
+ case 2:
+ return 1 << 2;
+ case 1:
+ return 1 << 1;
+ default:
+ return 1 << 0;
+ }
+ }
+
+ unsigned write_mask_from_swizzle(const ir_swizzle_mask& mask) const
+ {
+ unsigned result = 0;
+ switch(mask.num_components)
+ {
+ case 4:
+ result |= from_component(mask.w);
+ case 3:
+ result |= from_component(mask.z);
+ case 2:
+ result |= from_component(mask.y);
+ case 1:
+ result |= from_component(mask.x);
+ default:
+ break;
+ }
+ return result;
+ }
+
+
+
+public:
+ void handle_rvalue(ir_rvalue **rvalue)
+ {
+ if(!*rvalue)
+ return;
+ ir_rvalue* tmp_rvalue = *rvalue;
+ if(ir_dereference_variable* dref = tmp_rvalue->as_dereference_variable())
+ {
+ if(dref->var == var1)
+ {
+ ir_dereference_variable* ndref = new (packed_var) ir_dereference_variable(packed_var);
+ ir_swizzle* swz = new (dref) ir_swizzle(ndref,mask_for_var1);
+ *rvalue = swz;
+ }
+ if(dref->var == var2)
+ {
+ ir_dereference_variable* ndref = new (packed_var) ir_dereference_variable(packed_var);
+ ir_swizzle* swz = new (dref) ir_swizzle(ndref,mask_for_var2);
+ *rvalue = swz;
+ }
+ }
+ }
+
+ ir_visitor_status visit_enter(ir_assignment * assign)
+ {
+ assign->rhs->accept(this);
+ if(ir_dereference_variable* dref = assign->lhs->as_dereference_variable())
+ {
+ if(dref->var == var1)
+ {
+ dref->var = packed_var;
+ assign->write_mask = write_mask_from_swizzle(mask_for_var1);
+ }
+ if(dref->var == var2)
+ {
+ dref->var = packed_var;
+ assign->write_mask = write_mask_from_swizzle(mask_for_var2);
+ }
+ }
+ return visit_continue;
+ }
+
+ ir_variable_replacer(ir_variable* v1,ir_swizzle_mask mask1, ir_variable* v2, ir_swizzle_mask mask2, ir_variable* newvar):var1(v1),mask_for_var1(mask1), var2(v2),mask_for_var2(mask2), packed_var(newvar)
+ {
+ }
+};
+
+
+class ir_packer : public ir_hierarchical_visitor
+{
+public:
+ ir_visitor_status visit_enter(ir_function_signature * fonc)
+ {
+ int body_size = 0;
+ foreach_list_const(tmp,&(fonc->body))
+ {
+ body_size++;
+ }
+ if(!body_size)
+ return visit_continue;
+ //cout << "ENTERING " << fonc->function_name() << ":"<< endl;
+ ir_variable_lister v(fonc);
+ foreach_list(tmp,&(fonc->body))
+ {
+ ir_instruction* inst = (ir_instruction*) tmp;
+ inst->accept(&v);
+ }
+ ir_variable *v1=0,*v2=0;
+ ir_swizzle_mask m1,m2;
+ if(!v.find_candidates(v1,m1,v2,m2))
+ return visit_continue;
+ cout << "PACKING " << v1->name<< " WITH " << v2->name << endl;
+ ir_variable* newvar=0;
+ switch(m1.num_components + m2.num_components)
+ {
+ case 4:
+ newvar = new (fonc) ir_variable(glsl_type::vec4_type,"vec4_tmp",ir_var_temporary);
+ break;
+ case 3:
+ newvar = new (fonc) ir_variable(glsl_type::vec3_type,"vec3_tmp",ir_var_temporary);
+ break;
+ case 2:
+ newvar = new (fonc) ir_variable(glsl_type::vec2_type,"vec2_tmp",ir_var_temporary);
+ break;
+ }
+ fonc->body.push_head(newvar);
+ ir_variable_replacer vis2(v1,m1,v2,m2,newvar);
+ foreach_list(tmp,&(fonc->body))
+ {
+ ir_instruction* inst = (ir_instruction*) tmp;
+ inst->accept(&vis2);
+ }
+ return visit_continue;
+ }
+};
+
+
+bool
+do_var_packing(exec_list *instructions)
+{
+ ir_packer v;
+ for(int i=0;i<50;i++)
+ visit_list_elements(&v, instructions);
+
+
+ return false;
+}
--
1.7.3.4
More information about the mesa-dev
mailing list