diff options
Diffstat (limited to 'src/glsl')
-rw-r--r-- | src/glsl/ir_expression_flattening.cpp | 124 |
1 files changed, 14 insertions, 110 deletions
diff --git a/src/glsl/ir_expression_flattening.cpp b/src/glsl/ir_expression_flattening.cpp index ccb2e2bce9e..7b1b8dbfef1 100644 --- a/src/glsl/ir_expression_flattening.cpp +++ b/src/glsl/ir_expression_flattening.cpp @@ -35,15 +35,14 @@ #include "ir.h" #include "ir_visitor.h" +#include "ir_rvalue_visitor.h" #include "ir_expression_flattening.h" #include "glsl_types.h" -class ir_expression_flattening_visitor : public ir_hierarchical_visitor { +class ir_expression_flattening_visitor : public ir_rvalue_visitor { public: - ir_expression_flattening_visitor(ir_instruction *base_ir, - bool (*predicate)(ir_instruction *ir)) + ir_expression_flattening_visitor(bool (*predicate)(ir_instruction *ir)) { - this->base_ir = base_ir; this->predicate = predicate; } @@ -52,42 +51,34 @@ public: /* empty */ } - virtual ir_visitor_status visit_enter(ir_call *); - virtual ir_visitor_status visit_enter(ir_return *); - virtual ir_visitor_status visit_enter(ir_function_signature *); - virtual ir_visitor_status visit_enter(ir_if *); - virtual ir_visitor_status visit_enter(ir_loop *); - virtual ir_visitor_status visit_leave(ir_assignment *); - virtual ir_visitor_status visit_leave(ir_expression *); - virtual ir_visitor_status visit_leave(ir_swizzle *); - - ir_rvalue *operand_to_temp(ir_rvalue *val); + void handle_rvalue(ir_rvalue **rvalue); bool (*predicate)(ir_instruction *ir); - ir_instruction *base_ir; }; void do_expression_flattening(exec_list *instructions, bool (*predicate)(ir_instruction *ir)) { + ir_expression_flattening_visitor v(predicate); + foreach_iter(exec_list_iterator, iter, *instructions) { ir_instruction *ir = (ir_instruction *)iter.get(); - ir_expression_flattening_visitor v(ir, predicate); ir->accept(&v); } } - -ir_rvalue * -ir_expression_flattening_visitor::operand_to_temp(ir_rvalue *ir) +void +ir_expression_flattening_visitor::handle_rvalue(ir_rvalue **rvalue) { - void *ctx = base_ir; ir_variable *var; ir_assignment *assign; + ir_rvalue *ir = *rvalue; + + if (!ir || !this->predicate(ir)) + return; - if (!this->predicate(ir)) - return ir; + void *ctx = talloc_parent(ir); var = new(ctx) ir_variable(ir->type, "flattening_tmp", ir_var_temporary); base_ir->insert_before(var); @@ -97,92 +88,5 @@ ir_expression_flattening_visitor::operand_to_temp(ir_rvalue *ir) NULL); base_ir->insert_before(assign); - return new(ctx) ir_dereference_variable(var); -} - -ir_visitor_status -ir_expression_flattening_visitor::visit_enter(ir_function_signature *ir) -{ - do_expression_flattening(&ir->body, this->predicate); - - return visit_continue_with_parent; -} - -ir_visitor_status -ir_expression_flattening_visitor::visit_enter(ir_loop *ir) -{ - do_expression_flattening(&ir->body_instructions, this->predicate); - - return visit_continue_with_parent; -} - -ir_visitor_status -ir_expression_flattening_visitor::visit_enter(ir_if *ir) -{ - ir->condition->accept(this); - - do_expression_flattening(&ir->then_instructions, this->predicate); - do_expression_flattening(&ir->else_instructions, this->predicate); - - return visit_continue_with_parent; -} - -ir_visitor_status -ir_expression_flattening_visitor::visit_leave(ir_expression *ir) -{ - unsigned int operand; - - for (operand = 0; operand < ir->get_num_operands(); operand++) { - /* If the operand matches the predicate, then we'll assign its - * value to a temporary and deref the temporary as the operand. - */ - ir->operands[operand] = operand_to_temp(ir->operands[operand]); - } - - return visit_continue; -} - -ir_visitor_status -ir_expression_flattening_visitor::visit_leave(ir_assignment *ir) -{ - ir->rhs = operand_to_temp(ir->rhs); - if (ir->condition) - ir->condition = operand_to_temp(ir->condition); - - return visit_continue; -} - -ir_visitor_status -ir_expression_flattening_visitor::visit_leave(ir_swizzle *ir) -{ - if (this->predicate(ir->val)) { - ir->val = operand_to_temp(ir->val); - } - - return visit_continue; -} - -ir_visitor_status -ir_expression_flattening_visitor::visit_enter(ir_call *ir) -{ - /* Reminder: iterating ir_call iterates its parameters. */ - foreach_iter(exec_list_iterator, iter, *ir) { - ir_rvalue *ir = (ir_rvalue *)iter.get(); - ir_rvalue *new_ir = operand_to_temp(ir); - - if (new_ir != ir) { - ir->replace_with(new_ir); - } - } - - return visit_continue; -} - - -ir_visitor_status -ir_expression_flattening_visitor::visit_enter(ir_return *ir) -{ - if (ir->value) - ir->value = operand_to_temp(ir->value); - return visit_continue; + *rvalue = new(ctx) ir_dereference_variable(var); } |