diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | glsl_parser_extras.cpp | 1 | ||||
-rw-r--r-- | ir.h | 7 | ||||
-rw-r--r-- | ir_optimization.h | 1 | ||||
-rw-r--r-- | ir_vec_index_to_swizzle.cpp | 166 |
5 files changed, 176 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am index 42f0ae557e..c31f3969a8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,7 +47,8 @@ glsl_SOURCES = \ ir_reader.cpp s_expression.cpp \ ir_hv_accept.cpp \ ir_hierarchical_visitor.h \ - ir_hierarchical_visitor.cpp + ir_hierarchical_visitor.cpp \ + ir_vec_index_to_swizzle.cpp BUILT_SOURCES = glsl_parser.h glsl_parser.cpp glsl_lexer.cpp CLEANFILES = $(BUILT_SOURCES) diff --git a/glsl_parser_extras.cpp b/glsl_parser_extras.cpp index 62eeb9c860..e778e0f8f8 100644 --- a/glsl_parser_extras.cpp +++ b/glsl_parser_extras.cpp @@ -759,6 +759,7 @@ main(int argc, char **argv) progress = do_dead_code_local(&instructions) || progress; progress = do_dead_code_unlinked(&instructions) || progress; progress = do_constant_folding(&instructions) || progress; + progress = do_vec_index_to_swizzle(&instructions) || progress; } while (progress); } @@ -56,6 +56,7 @@ public: virtual class ir_variable * as_variable() { return NULL; } virtual class ir_function * as_function() { return NULL; } virtual class ir_dereference * as_dereference() { return NULL; } + virtual class ir_dereference_array * as_dereference_array() { return NULL; } virtual class ir_rvalue * as_rvalue() { return NULL; } virtual class ir_label * as_label() { return NULL; } virtual class ir_loop * as_loop() { return NULL; } @@ -685,7 +686,6 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); -private: ir_rvalue *value; }; @@ -860,6 +860,11 @@ public: ir_dereference_array(ir_variable *var, ir_rvalue *array_index); + virtual ir_dereference_array *as_dereference_array() + { + return this; + } + /** * Get the variable that is ultimately referenced by an r-value */ diff --git a/ir_optimization.h b/ir_optimization.h index d9e30ce08c..2916784723 100644 --- a/ir_optimization.h +++ b/ir_optimization.h @@ -35,3 +35,4 @@ bool do_dead_code_local(exec_list *instructions); bool do_dead_code_unlinked(exec_list *instructions); bool do_function_inlining(exec_list *instructions); bool do_if_simplification(exec_list *instructions); +bool do_vec_index_to_swizzle(exec_list *instructions); diff --git a/ir_vec_index_to_swizzle.cpp b/ir_vec_index_to_swizzle.cpp new file mode 100644 index 0000000000..1deb0d381e --- /dev/null +++ b/ir_vec_index_to_swizzle.cpp @@ -0,0 +1,166 @@ +/* + * Copyright © 2010 Intel Corporation + * + * 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. + */ + +/** + * \file ir_vec_index_to_swizzle.cpp + * + * Turns constant indexing into vector types to swizzles. This will + * let other swizzle-aware optimization passes catch these constructs, + * and codegen backends not have to worry about this case. + */ + +#include <stdio.h> +#include "ir.h" +#include "ir_visitor.h" +#include "ir_optimization.h" +#include "ir_print_visitor.h" +#include "glsl_types.h" + +/** + * Visitor class for replacing expressions with ir_constant values. + */ + +class ir_vec_index_to_swizzle_visitor : public ir_hierarchical_visitor { +public: + ir_vec_index_to_swizzle_visitor() + { + progress = false; + } + + ir_rvalue *convert_vec_index_to_swizzle(ir_rvalue *val); + + virtual ir_visitor_status visit_enter(ir_expression *); + virtual ir_visitor_status visit_enter(ir_swizzle *); + virtual ir_visitor_status visit_enter(ir_assignment *); + virtual ir_visitor_status visit_enter(ir_return *); + virtual ir_visitor_status visit_enter(ir_call *); + virtual ir_visitor_status visit_enter(ir_if *); + + bool progress; +}; + +ir_rvalue * +ir_vec_index_to_swizzle_visitor::convert_vec_index_to_swizzle(ir_rvalue *ir) +{ + ir_dereference_array *deref = ir->as_dereference_array(); + ir_constant *ir_constant; + ir_rvalue *deref_var; + + if (!deref) + return ir; + + if (deref->array->type->is_matrix() || deref->array->type->is_array()) + return ir; + + deref_var = deref->array->as_rvalue(); + if (!deref_var) { + ir_variable *var = deref->array->as_variable(); + assert(var); + deref_var = new ir_dereference_variable(var); + } + + assert(deref->array_index->type->base_type == GLSL_TYPE_INT); + ir_constant = deref->array_index->constant_expression_value(); + if (!ir_constant) + return ir; + + this->progress = true; + return new ir_swizzle(deref_var, ir_constant->value.i[0], 0, 0, 0, 1); +} + +ir_visitor_status +ir_vec_index_to_swizzle_visitor::visit_enter(ir_expression *ir) +{ + unsigned int i; + + for (i = 0; i < ir->get_num_operands(); i++) { + ir->operands[i] = convert_vec_index_to_swizzle(ir->operands[i]); + } + + return visit_continue; +} + +ir_visitor_status +ir_vec_index_to_swizzle_visitor::visit_enter(ir_swizzle *ir) +{ + /* Can't be hit from normal GLSL, since you can't swizzle a scalar (which + * the result of indexing a vector is. But maybe at some point we'll end up + * using swizzling of scalars for vector construction. + */ + ir->val = convert_vec_index_to_swizzle(ir->val); + + return visit_continue; +} + +ir_visitor_status +ir_vec_index_to_swizzle_visitor::visit_enter(ir_assignment *ir) +{ + ir->lhs = convert_vec_index_to_swizzle(ir->lhs); + ir->rhs = convert_vec_index_to_swizzle(ir->rhs); + + return visit_continue; +} + +ir_visitor_status +ir_vec_index_to_swizzle_visitor::visit_enter(ir_call *ir) +{ + foreach_iter(exec_list_iterator, iter, *ir) { + ir_rvalue *param = (ir_rvalue *)iter.get(); + ir_rvalue *new_param = convert_vec_index_to_swizzle(param); + + if (new_param != param) { + param->insert_before(new_param); + param->remove(); + } + } + + return visit_continue; +} + +ir_visitor_status +ir_vec_index_to_swizzle_visitor::visit_enter(ir_return *ir) +{ + if (ir->value) { + ir->value = convert_vec_index_to_swizzle(ir->value); + } + + return visit_continue; +} + +ir_visitor_status +ir_vec_index_to_swizzle_visitor::visit_enter(ir_if *ir) +{ + ir->condition = convert_vec_index_to_swizzle(ir->condition); + + return visit_continue; +} + +bool +do_vec_index_to_swizzle(exec_list *instructions) +{ + ir_vec_index_to_swizzle_visitor v; + + v.run(instructions); + + return false; +} |