diff options
Diffstat (limited to 'mesalib/src/glsl/opt_algebraic.cpp')
-rw-r--r-- | mesalib/src/glsl/opt_algebraic.cpp | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp index 9d5539252..ac7514acf 100644 --- a/mesalib/src/glsl/opt_algebraic.cpp +++ b/mesalib/src/glsl/opt_algebraic.cpp @@ -45,7 +45,9 @@ namespace { class ir_algebraic_visitor : public ir_rvalue_visitor { public: - ir_algebraic_visitor(bool native_integers) + ir_algebraic_visitor(bool native_integers, + const struct gl_shader_compiler_options *options) + : options(options) { this->progress = false; this->mem_ctx = NULL; @@ -69,6 +71,7 @@ public: ir_rvalue *swizzle_if_required(ir_expression *expr, ir_rvalue *operand); + const struct gl_shader_compiler_options *options; void *mem_ctx; bool native_integers; @@ -116,6 +119,46 @@ update_type(ir_expression *ir) ir->type = ir->operands[1]->type; } +/* Recognize (v.x + v.y) + (v.z + v.w) as dot(v, 1.0) */ +static ir_expression * +try_replace_with_dot(ir_expression *expr0, ir_expression *expr1, void *mem_ctx) +{ + if (expr0 && expr0->operation == ir_binop_add && + expr0->type->is_float() && + expr1 && expr1->operation == ir_binop_add && + expr1->type->is_float()) { + ir_swizzle *x = expr0->operands[0]->as_swizzle(); + ir_swizzle *y = expr0->operands[1]->as_swizzle(); + ir_swizzle *z = expr1->operands[0]->as_swizzle(); + ir_swizzle *w = expr1->operands[1]->as_swizzle(); + + if (!x || x->mask.num_components != 1 || + !y || y->mask.num_components != 1 || + !z || z->mask.num_components != 1 || + !w || w->mask.num_components != 1) { + return NULL; + } + + bool swiz_seen[4] = {false, false, false, false}; + swiz_seen[x->mask.x] = true; + swiz_seen[y->mask.x] = true; + swiz_seen[z->mask.x] = true; + swiz_seen[w->mask.x] = true; + + if (!swiz_seen[0] || !swiz_seen[1] || + !swiz_seen[2] || !swiz_seen[3]) { + return NULL; + } + + if (x->val->equals(y->val) && + x->val->equals(z->val) && + x->val->equals(w->val)) { + return dot(x->val, new(mem_ctx) ir_constant(1.0f, 4)); + } + } + return NULL; +} + void ir_algebraic_visitor::reassociate_operands(ir_expression *ir1, int op1, @@ -329,6 +372,14 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) if (op_const[1] && !op_const[0]) reassociate_constant(ir, 1, op_const[1], op_expr[0]); + /* Recognize (v.x + v.y) + (v.z + v.w) as dot(v, 1.0) */ + if (options->OptimizeForAOS) { + ir_expression *expr = try_replace_with_dot(op_expr[0], op_expr[1], + mem_ctx); + if (expr) + return expr; + } + /* Replace (-x + y) * a + x and commutative variations with lrp(x, y, a). * * (-x + y) * a + x @@ -380,6 +431,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) } } } + break; case ir_binop_sub: @@ -647,9 +699,10 @@ ir_algebraic_visitor::handle_rvalue(ir_rvalue **rvalue) } bool -do_algebraic(exec_list *instructions, bool native_integers) +do_algebraic(exec_list *instructions, bool native_integers, + const struct gl_shader_compiler_options *options) { - ir_algebraic_visitor v(native_integers); + ir_algebraic_visitor v(native_integers, options); visit_list_elements(&v, instructions); |