From 29285882676388aacff123e8bdf025904abf8ea9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 24 Jun 2010 15:32:15 -0700 Subject: glsl2: Move the compiler to the subdirectory it will live in in Mesa. --- src/glsl/ir_constant_folding.cpp | 229 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 src/glsl/ir_constant_folding.cpp (limited to 'src/glsl/ir_constant_folding.cpp') diff --git a/src/glsl/ir_constant_folding.cpp b/src/glsl/ir_constant_folding.cpp new file mode 100644 index 00000000000..342d027bbe8 --- /dev/null +++ b/src/glsl/ir_constant_folding.cpp @@ -0,0 +1,229 @@ +/* + * 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_constant_folding.cpp + * Replace constant-valued expressions with references to constant values. + */ + +#include "ir.h" +#include "ir_visitor.h" +#include "ir_optimization.h" +#include "glsl_types.h" + +/** + * Visitor class for replacing expressions with ir_constant values. + */ + +class ir_constant_folding_visitor : public ir_visitor { +public: + ir_constant_folding_visitor() + { + /* empty */ + } + + virtual ~ir_constant_folding_visitor() + { + /* empty */ + } + + /** + * \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_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 *); + virtual void visit(ir_loop *); + virtual void visit(ir_loop_jump *); + /*@}*/ +}; + +void +ir_constant_folding_visitor::visit(ir_variable *ir) +{ + (void) ir; +} + + +void +ir_constant_folding_visitor::visit(ir_function_signature *ir) +{ + visit_exec_list(&ir->body, this); +} + + +void +ir_constant_folding_visitor::visit(ir_function *ir) +{ + foreach_iter(exec_list_iterator, iter, *ir) { + ir_function_signature *const sig = (ir_function_signature *) iter.get(); + sig->accept(this); + } +} + +void +ir_constant_folding_visitor::visit(ir_expression *ir) +{ + ir_constant *op[2]; + unsigned int operand; + + for (operand = 0; operand < ir->get_num_operands(); operand++) { + op[operand] = ir->operands[operand]->constant_expression_value(); + if (op[operand]) { + ir->operands[operand] = op[operand]; + } else { + ir->operands[operand]->accept(this); + } + } +} + + +void +ir_constant_folding_visitor::visit(ir_texture *ir) +{ + // FINISHME: Do stuff with texture lookups + (void) ir; +} + + +void +ir_constant_folding_visitor::visit(ir_swizzle *ir) +{ + ir->val->accept(this); +} + + +void +ir_constant_folding_visitor::visit(ir_dereference_variable *ir) +{ + (void) ir; +} + + +void +ir_constant_folding_visitor::visit(ir_dereference_array *ir) +{ + ir_constant *const_val = + ir->array_index->constant_expression_value(); + + if (const_val) + ir->array_index = const_val; + else + ir->array_index->accept(this); + + ir->array->accept(this); +} + + +void +ir_constant_folding_visitor::visit(ir_dereference_record *ir) +{ + ir->record->accept(this); +} + + +void +ir_constant_folding_visitor::visit(ir_assignment *ir) +{ + ir_constant *const_val = ir->rhs->constant_expression_value(); + if (const_val) + ir->rhs = const_val; + else + ir->rhs->accept(this); +} + + +void +ir_constant_folding_visitor::visit(ir_constant *ir) +{ + (void) ir; +} + + +void +ir_constant_folding_visitor::visit(ir_call *ir) +{ + (void) ir; +} + + +void +ir_constant_folding_visitor::visit(ir_return *ir) +{ + (void) ir; +} + + +void +ir_constant_folding_visitor::visit(ir_if *ir) +{ + ir_constant *const_val = ir->condition->constant_expression_value(); + if (const_val) + ir->condition = const_val; + else + ir->condition->accept(this); + + visit_exec_list(&ir->then_instructions, this); + visit_exec_list(&ir->else_instructions, this); +} + + +void +ir_constant_folding_visitor::visit(ir_loop *ir) +{ + (void) ir; +} + + +void +ir_constant_folding_visitor::visit(ir_loop_jump *ir) +{ + (void) ir; +} + +bool +do_constant_folding(exec_list *instructions) +{ + ir_constant_folding_visitor constant_folding; + + visit_exec_list(instructions, &constant_folding); + + /* FINISHME: Return real progress. */ + return false; +} -- cgit v1.2.3 From 16efab1c4dee6e6a827ba5f1c482378159545ae5 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 30 Jun 2010 10:47:34 -0700 Subject: glsl2: Define new ir_discard instruction. --- src/glsl/ir.h | 27 +++++++++++++++++++++++++++ src/glsl/ir_clone.cpp | 12 ++++++++++++ src/glsl/ir_constant_expression.cpp | 9 +++++++++ src/glsl/ir_constant_folding.cpp | 8 ++++++++ src/glsl/ir_hierarchical_visitor.cpp | 16 ++++++++++++++++ src/glsl/ir_hierarchical_visitor.h | 2 ++ src/glsl/ir_hv_accept.cpp | 17 +++++++++++++++++ src/glsl/ir_print_visitor.cpp | 14 ++++++++++++++ src/glsl/ir_print_visitor.h | 1 + src/glsl/ir_visitor.h | 1 + src/mesa/shader/ir_to_mesa.cpp | 8 ++++++++ 11 files changed, 115 insertions(+) (limited to 'src/glsl/ir_constant_folding.cpp') diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 65026ef1f5b..00b0076c172 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -793,6 +793,33 @@ private: /** Loop containing this break instruction. */ ir_loop *loop; }; + +/** + * IR instruction representing discard statements. + */ +class ir_discard : public ir_jump { +public: + ir_discard() + { + this->condition = NULL; + } + + ir_discard(ir_rvalue *cond) + { + this->condition = cond; + } + + virtual ir_instruction *clone(struct hash_table *ht) const; + + virtual void accept(ir_visitor *v) + { + v->visit(this); + } + + virtual ir_visitor_status accept(ir_hierarchical_visitor *); + + ir_rvalue *condition; +}; /*@}*/ diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 01a1ce3a6d4..74cc858bda4 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -74,6 +74,18 @@ ir_return::clone(struct hash_table *ht) const return new(ctx) ir_return(new_value); } +ir_instruction * +ir_discard::clone(struct hash_table *ht) const +{ + void *ctx = talloc_parent(this); + ir_rvalue *new_condition = NULL; + + if (this->condition != NULL) + new_condition = (ir_rvalue *) this->condition->clone(ht); + + return new(ctx) ir_discard(new_condition); +} + ir_instruction * ir_loop_jump::clone(struct hash_table *ht) const { diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index 3408f5256a7..c6348ac4347 100644 --- a/src/glsl/ir_constant_expression.cpp +++ b/src/glsl/ir_constant_expression.cpp @@ -75,6 +75,7 @@ public: virtual void visit(ir_constant *); virtual void visit(ir_call *); virtual void visit(ir_return *); + virtual void visit(ir_discard *); virtual void visit(ir_if *); virtual void visit(ir_loop *); virtual void visit(ir_loop_jump *); @@ -647,6 +648,14 @@ ir_constant_visitor::visit(ir_return *ir) } +void +ir_constant_visitor::visit(ir_discard *ir) +{ + (void) ir; + value = NULL; +} + + void ir_constant_visitor::visit(ir_if *ir) { diff --git a/src/glsl/ir_constant_folding.cpp b/src/glsl/ir_constant_folding.cpp index 342d027bbe8..2daa6fde38d 100644 --- a/src/glsl/ir_constant_folding.cpp +++ b/src/glsl/ir_constant_folding.cpp @@ -68,6 +68,7 @@ public: virtual void visit(ir_constant *); virtual void visit(ir_call *); virtual void visit(ir_return *); + virtual void visit(ir_discard *); virtual void visit(ir_if *); virtual void visit(ir_loop *); virtual void visit(ir_loop_jump *); @@ -190,6 +191,13 @@ ir_constant_folding_visitor::visit(ir_return *ir) } +void +ir_constant_folding_visitor::visit(ir_discard *ir) +{ + (void) ir; +} + + void ir_constant_folding_visitor::visit(ir_if *ir) { diff --git a/src/glsl/ir_hierarchical_visitor.cpp b/src/glsl/ir_hierarchical_visitor.cpp index 0d520b127f2..9afb12a4a2b 100644 --- a/src/glsl/ir_hierarchical_visitor.cpp +++ b/src/glsl/ir_hierarchical_visitor.cpp @@ -242,6 +242,22 @@ ir_hierarchical_visitor::visit_leave(ir_return *ir) return visit_continue; } +ir_visitor_status +ir_hierarchical_visitor::visit_enter(ir_discard *ir) +{ + if (this->callback != NULL) + this->callback(ir, this->data); + + return visit_continue; +} + +ir_visitor_status +ir_hierarchical_visitor::visit_leave(ir_discard *ir) +{ + (void) ir; + return visit_continue; +} + ir_visitor_status ir_hierarchical_visitor::visit_enter(ir_if *ir) { diff --git a/src/glsl/ir_hierarchical_visitor.h b/src/glsl/ir_hierarchical_visitor.h index 8b9e49dab13..2c4590d4b10 100644 --- a/src/glsl/ir_hierarchical_visitor.h +++ b/src/glsl/ir_hierarchical_visitor.h @@ -129,6 +129,8 @@ public: virtual ir_visitor_status visit_leave(class ir_call *); virtual ir_visitor_status visit_enter(class ir_return *); virtual ir_visitor_status visit_leave(class ir_return *); + virtual ir_visitor_status visit_enter(class ir_discard *); + virtual ir_visitor_status visit_leave(class ir_discard *); virtual ir_visitor_status visit_enter(class ir_if *); virtual ir_visitor_status visit_leave(class ir_if *); /*@}*/ diff --git a/src/glsl/ir_hv_accept.cpp b/src/glsl/ir_hv_accept.cpp index f936b3500eb..7b5cc5234c5 100644 --- a/src/glsl/ir_hv_accept.cpp +++ b/src/glsl/ir_hv_accept.cpp @@ -321,6 +321,23 @@ ir_return::accept(ir_hierarchical_visitor *v) } +ir_visitor_status +ir_discard::accept(ir_hierarchical_visitor *v) +{ + ir_visitor_status s = v->visit_enter(this); + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + + if (this->condition != NULL) { + s = this->condition->accept(v); + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + } + + return v->visit_leave(this); +} + + ir_visitor_status ir_if::accept(ir_hierarchical_visitor *v) { diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp index be5a843f67d..6f867e32532 100644 --- a/src/glsl/ir_print_visitor.cpp +++ b/src/glsl/ir_print_visitor.cpp @@ -314,6 +314,20 @@ ir_print_visitor::visit(ir_return *ir) } +void +ir_print_visitor::visit(ir_discard *ir) +{ + printf("(discard "); + + if (ir->condition != NULL) { + printf(" "); + ir->condition->accept(this); + } + + printf(")"); +} + + void ir_print_visitor::visit(ir_if *ir) { diff --git a/src/glsl/ir_print_visitor.h b/src/glsl/ir_print_visitor.h index e97b823522a..3db42e24ca3 100644 --- a/src/glsl/ir_print_visitor.h +++ b/src/glsl/ir_print_visitor.h @@ -69,6 +69,7 @@ public: virtual void visit(ir_constant *); virtual void visit(ir_call *); virtual void visit(ir_return *); + virtual void visit(ir_discard *); virtual void visit(ir_if *); virtual void visit(ir_loop *); virtual void visit(ir_loop_jump *); diff --git a/src/glsl/ir_visitor.h b/src/glsl/ir_visitor.h index a6f9d2b7ee3..b87d7373180 100644 --- a/src/glsl/ir_visitor.h +++ b/src/glsl/ir_visitor.h @@ -57,6 +57,7 @@ public: virtual void visit(class ir_constant *) = 0; virtual void visit(class ir_call *) = 0; virtual void visit(class ir_return *) = 0; + virtual void visit(class ir_discard *) = 0; virtual void visit(class ir_if *) = 0; virtual void visit(class ir_loop *) = 0; virtual void visit(class ir_loop_jump *) = 0; diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp index ef9a96e2f52..8c074a8bd9a 100644 --- a/src/mesa/shader/ir_to_mesa.cpp +++ b/src/mesa/shader/ir_to_mesa.cpp @@ -134,6 +134,7 @@ public: virtual void visit(ir_constant *); virtual void visit(ir_call *); virtual void visit(ir_return *); + virtual void visit(ir_discard *); virtual void visit(ir_texture *); virtual void visit(ir_if *); /*@}*/ @@ -1321,6 +1322,13 @@ ir_to_mesa_visitor::visit(ir_return *ir) ir->get_value()->accept(this); } +void +ir_to_mesa_visitor::visit(ir_discard *ir) +{ + assert(0); + + ir->condition->accept(this); +} void ir_to_mesa_visitor::visit(ir_if *ir) -- cgit v1.2.3 From 14f8e16132409f38656e4874aa53bc471977f9ad Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 Jul 2010 11:43:28 -0700 Subject: glsl2: Constant-fold assignment conditions. --- src/glsl/ir_constant_folding.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/glsl/ir_constant_folding.cpp') diff --git a/src/glsl/ir_constant_folding.cpp b/src/glsl/ir_constant_folding.cpp index 2daa6fde38d..66a92e9f3b6 100644 --- a/src/glsl/ir_constant_folding.cpp +++ b/src/glsl/ir_constant_folding.cpp @@ -167,6 +167,19 @@ ir_constant_folding_visitor::visit(ir_assignment *ir) ir->rhs = const_val; else ir->rhs->accept(this); + + if (ir->condition) { + /* If the condition is constant, either remove the condition or + * remove the never-executed assignment. + */ + const_val = ir->condition->constant_expression_value(); + if (const_val) { + if (const_val->value.b[0]) + ir->condition = NULL; + else + ir->remove(); + } + } } -- cgit v1.2.3 From 3d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Aug 2010 16:06:00 -0700 Subject: glsl2: Refactor constant folding of rvalues to a function. --- src/glsl/ir_constant_folding.cpp | 47 ++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 26 deletions(-) (limited to 'src/glsl/ir_constant_folding.cpp') diff --git a/src/glsl/ir_constant_folding.cpp b/src/glsl/ir_constant_folding.cpp index 66a92e9f3b6..492036e9a6b 100644 --- a/src/glsl/ir_constant_folding.cpp +++ b/src/glsl/ir_constant_folding.cpp @@ -73,8 +73,24 @@ public: virtual void visit(ir_loop *); virtual void visit(ir_loop_jump *); /*@}*/ + + void fold_constant(ir_rvalue **rvalue); }; +void +ir_constant_folding_visitor::fold_constant(ir_rvalue **rvalue) +{ + if ((*rvalue)->ir_type == ir_type_constant) + return; + + ir_constant *constant = (*rvalue)->constant_expression_value(); + if (constant) { + *rvalue = constant; + } else { + (*rvalue)->accept(this); + } +} + void ir_constant_folding_visitor::visit(ir_variable *ir) { @@ -101,16 +117,10 @@ ir_constant_folding_visitor::visit(ir_function *ir) void ir_constant_folding_visitor::visit(ir_expression *ir) { - ir_constant *op[2]; unsigned int operand; for (operand = 0; operand < ir->get_num_operands(); operand++) { - op[operand] = ir->operands[operand]->constant_expression_value(); - if (op[operand]) { - ir->operands[operand] = op[operand]; - } else { - ir->operands[operand]->accept(this); - } + fold_constant(&ir->operands[operand]); } } @@ -140,14 +150,7 @@ ir_constant_folding_visitor::visit(ir_dereference_variable *ir) void ir_constant_folding_visitor::visit(ir_dereference_array *ir) { - ir_constant *const_val = - ir->array_index->constant_expression_value(); - - if (const_val) - ir->array_index = const_val; - else - ir->array_index->accept(this); - + fold_constant(&ir->array_index); ir->array->accept(this); } @@ -162,17 +165,13 @@ ir_constant_folding_visitor::visit(ir_dereference_record *ir) void ir_constant_folding_visitor::visit(ir_assignment *ir) { - ir_constant *const_val = ir->rhs->constant_expression_value(); - if (const_val) - ir->rhs = const_val; - else - ir->rhs->accept(this); + fold_constant(&ir->rhs); if (ir->condition) { /* If the condition is constant, either remove the condition or * remove the never-executed assignment. */ - const_val = ir->condition->constant_expression_value(); + ir_constant *const_val = ir->condition->constant_expression_value(); if (const_val) { if (const_val->value.b[0]) ir->condition = NULL; @@ -214,11 +213,7 @@ ir_constant_folding_visitor::visit(ir_discard *ir) void ir_constant_folding_visitor::visit(ir_if *ir) { - ir_constant *const_val = ir->condition->constant_expression_value(); - if (const_val) - ir->condition = const_val; - else - ir->condition->accept(this); + fold_constant(&ir->condition); visit_exec_list(&ir->then_instructions, this); visit_exec_list(&ir->else_instructions, this); -- cgit v1.2.3 From 6ecf62f673bf90d0969f8db032781b49a988975a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Aug 2010 16:07:41 -0700 Subject: glsl2: Return a real progress value from constant folding. --- src/glsl/ir_constant_folding.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/glsl/ir_constant_folding.cpp') diff --git a/src/glsl/ir_constant_folding.cpp b/src/glsl/ir_constant_folding.cpp index 492036e9a6b..a6d82e33ec4 100644 --- a/src/glsl/ir_constant_folding.cpp +++ b/src/glsl/ir_constant_folding.cpp @@ -39,7 +39,7 @@ class ir_constant_folding_visitor : public ir_visitor { public: ir_constant_folding_visitor() { - /* empty */ + this->progress = false; } virtual ~ir_constant_folding_visitor() @@ -75,6 +75,8 @@ public: /*@}*/ void fold_constant(ir_rvalue **rvalue); + + bool progress; }; void @@ -86,6 +88,7 @@ ir_constant_folding_visitor::fold_constant(ir_rvalue **rvalue) ir_constant *constant = (*rvalue)->constant_expression_value(); if (constant) { *rvalue = constant; + this->progress = true; } else { (*rvalue)->accept(this); } @@ -178,6 +181,7 @@ ir_constant_folding_visitor::visit(ir_assignment *ir) else ir->remove(); } + this->progress = true; } } @@ -240,6 +244,5 @@ do_constant_folding(exec_list *instructions) visit_exec_list(instructions, &constant_folding); - /* FINISHME: Return real progress. */ - return false; + return constant_folding.progress; } -- cgit v1.2.3 From 8dbdcb0b43c8749018ff62dd5751190e54fe2445 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Aug 2010 16:18:18 -0700 Subject: glsl2: Constant fold the children of many more ir_instruction types. --- src/glsl/ir_constant_folding.cpp | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'src/glsl/ir_constant_folding.cpp') diff --git a/src/glsl/ir_constant_folding.cpp b/src/glsl/ir_constant_folding.cpp index a6d82e33ec4..11260423d90 100644 --- a/src/glsl/ir_constant_folding.cpp +++ b/src/glsl/ir_constant_folding.cpp @@ -82,7 +82,7 @@ public: void ir_constant_folding_visitor::fold_constant(ir_rvalue **rvalue) { - if ((*rvalue)->ir_type == ir_type_constant) + if (*rvalue == NULL || (*rvalue)->ir_type == ir_type_constant) return; ir_constant *constant = (*rvalue)->constant_expression_value(); @@ -131,15 +131,32 @@ ir_constant_folding_visitor::visit(ir_expression *ir) void ir_constant_folding_visitor::visit(ir_texture *ir) { - // FINISHME: Do stuff with texture lookups - (void) ir; + fold_constant(&ir->coordinate); + fold_constant(&ir->projector); + fold_constant(&ir->shadow_comparitor); + + switch (ir->op) { + case ir_tex: + break; + case ir_txb: + fold_constant(&ir->lod_info.bias); + break; + case ir_txf: + case ir_txl: + fold_constant(&ir->lod_info.lod); + break; + case ir_txd: + fold_constant(&ir->lod_info.grad.dPdx); + fold_constant(&ir->lod_info.grad.dPdy); + break; + } } void ir_constant_folding_visitor::visit(ir_swizzle *ir) { - ir->val->accept(this); + fold_constant(&ir->val); } @@ -180,8 +197,8 @@ ir_constant_folding_visitor::visit(ir_assignment *ir) ir->condition = NULL; else ir->remove(); + this->progress = true; } - this->progress = true; } } @@ -196,14 +213,22 @@ ir_constant_folding_visitor::visit(ir_constant *ir) void ir_constant_folding_visitor::visit(ir_call *ir) { - (void) ir; + foreach_iter(exec_list_iterator, iter, *ir) { + ir_rvalue *param = (ir_rvalue *)iter.get(); + ir_rvalue *new_param = param; + fold_constant(&new_param); + + if (new_param != param) { + param->replace_with(new_param); + } + } } void ir_constant_folding_visitor::visit(ir_return *ir) { - (void) ir; + fold_constant(&ir->value); } -- cgit v1.2.3