From 93ed12672618a2e321cb79a3b3a656aae63d6beb Mon Sep 17 00:00:00 2001 From: marha Date: Tue, 9 Aug 2011 08:20:19 +0200 Subject: xrandrproto mesa git update 9 aug 2011 --- mesalib/src/glsl/ast.h | 3 +- mesalib/src/glsl/ast_function.cpp | 18 +- mesalib/src/glsl/ast_to_hir.cpp | 44 ++--- mesalib/src/glsl/glsl_parser_extras.h | 6 + mesalib/src/glsl/ir_function.cpp | 2 +- mesalib/src/glsl/link_functions.cpp | 6 +- mesalib/src/glsl/linker.cpp | 8 + mesalib/src/glsl/opt_dead_functions.cpp | 319 ++++++++++++++++---------------- 8 files changed, 212 insertions(+), 194 deletions(-) (limited to 'mesalib/src/glsl') diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index 878f48b20..d1de22718 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -730,7 +730,6 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr, struct _mesa_glsl_parse_state *state); void -emit_function(_mesa_glsl_parse_state *state, exec_list *instructions, - ir_function *f); +emit_function(_mesa_glsl_parse_state *state, ir_function *f); #endif /* AST_H */ diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp index 8bcf48dfd..5b6ed3bc8 100644 --- a/mesalib/src/glsl/ast_function.cpp +++ b/mesalib/src/glsl/ast_function.cpp @@ -125,7 +125,7 @@ match_function_by_name(exec_list *instructions, const char *name, if (f == NULL) { f = new(ctx) ir_function(name); state->symbols->add_global_function(f); - emit_function(state, instructions, f); + emit_function(state, f); } f->add_signature(sig->clone_prototype(f, NULL)); @@ -199,6 +199,20 @@ match_function_by_name(exec_list *instructions, const char *name, */ ir_call *call = new(ctx) ir_call(sig, actual_parameters); if (!sig->return_type->is_void()) { + /* If the function call is a constant expression, don't + * generate the instructions to call it; just generate an + * ir_constant representing the constant value. + * + * Function calls can only be constant expressions starting + * in GLSL 1.20. + */ + if (state->language_version >= 120) { + ir_constant *const_val = call->constant_expression_value(); + if (const_val) { + return const_val; + } + } + ir_variable *var; ir_dereference_variable *deref; @@ -211,8 +225,6 @@ match_function_by_name(exec_list *instructions, const char *name, deref = new(ctx) ir_dereference_variable(var); ir_assignment *assign = new(ctx) ir_assignment(deref, call, NULL); instructions->push_tail(assign); - if (state->language_version >= 120) - var->constant_value = call->constant_expression_value(); deref = new(ctx) ir_dereference_variable(var); return deref; diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index 7da146119..2025911ac 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -66,6 +66,8 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) state->current_function = NULL; + state->toplevel_ir = instructions; + /* Section 4.2 of the GLSL 1.20 specification states: * "The built-in functions are scoped in a scope outside the global scope * users declare global variables in. That is, a shader's global scope, @@ -85,6 +87,8 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) ast->hir(instructions, state); detect_recursion_unlinked(state, instructions); + + state->toplevel_ir = NULL; } @@ -1765,11 +1769,6 @@ process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size, ir_rvalue *const ir = array_size->hir(& dummy_instructions, state); YYLTYPE loc = array_size->get_location(); - /* FINISHME: Verify that the grammar forbids side-effects in array - * FINISHME: sizes. i.e., 'vec4 [x = 12] data' - */ - assert(dummy_instructions.is_empty()); - if (ir != NULL) { if (!ir->type->is_integer()) { _mesa_glsl_error(& loc, state, "array size must be integer type"); @@ -1786,6 +1785,14 @@ process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size, } else { assert(size->type == ir->type); length = size->value.u[0]; + + /* If the array size is const (and we've verified that + * it is) then no instructions should have been emitted + * when we converted it to HIR. If they were emitted, + * then either the array size isn't const after all, or + * we are emitting unnecessary instructions. + */ + assert(dummy_instructions.is_empty()); } } } @@ -2926,23 +2933,16 @@ ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters, void -emit_function(_mesa_glsl_parse_state *state, exec_list *instructions, - ir_function *f) +emit_function(_mesa_glsl_parse_state *state, ir_function *f) { - /* Emit the new function header */ - if (state->current_function == NULL) { - instructions->push_tail(f); - } else { - /* IR invariants disallow function declarations or definitions nested - * within other function definitions. Insert the new ir_function - * block in the instruction sequence before the ir_function block - * containing the current ir_function_signature. - */ - ir_function *const curr = - const_cast(state->current_function->function()); - - curr->insert_before(f); - } + /* IR invariants disallow function declarations or definitions + * nested within other function definitions. But there is no + * requirement about the relative order of function declarations + * and definitions with respect to one another. So simply insert + * the new ir_function block at the end of the toplevel instruction + * list. + */ + state->toplevel_ir->push_tail(f); } @@ -3069,7 +3069,7 @@ ast_function::hir(exec_list *instructions, return NULL; } - emit_function(state, instructions, f); + emit_function(state, f); } /* Verify the return type of main() */ diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index 2f4d3cba7..fc392da5b 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -129,6 +129,12 @@ struct _mesa_glsl_parse_state { */ class ir_function_signature *current_function; + /** + * During AST to IR conversion, pointer to the toplevel IR + * instruction list being generated. + */ + exec_list *toplevel_ir; + /** Have we found a return statement in this function? */ bool found_return; diff --git a/mesalib/src/glsl/ir_function.cpp b/mesalib/src/glsl/ir_function.cpp index 2a4de5b0d..51d32b46f 100644 --- a/mesalib/src/glsl/ir_function.cpp +++ b/mesalib/src/glsl/ir_function.cpp @@ -27,7 +27,7 @@ typedef enum { PARAMETER_LIST_NO_MATCH, PARAMETER_LIST_EXACT_MATCH, - PARAMETER_LIST_INEXACT_MATCH, /*< Match requires implicit conversion. */ + PARAMETER_LIST_INEXACT_MATCH /*< Match requires implicit conversion. */ } parameter_list_match_t; /** diff --git a/mesalib/src/glsl/link_functions.cpp b/mesalib/src/glsl/link_functions.cpp index d40f771e3..acee32712 100644 --- a/mesalib/src/glsl/link_functions.cpp +++ b/mesalib/src/glsl/link_functions.cpp @@ -104,10 +104,12 @@ public: if (f == NULL) { f = new(linked) ir_function(name); - /* Add the new function to the linked IR. + /* Add the new function to the linked IR. Put it at the end + * so that it comes after any global variable declarations + * that it refers to. */ linked->symbols->add_function(f); - linked->ir->push_head(f); + linked->ir->push_tail(f); } ir_function_signature *linked_sig = diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 19eb9b5ff..b54ef4108 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -922,6 +922,14 @@ link_intrastage_shaders(void *mem_ctx, free(linking_shaders); +#ifdef DEBUG + /* At this point linked should contain all of the linked IR, so + * validate it to make sure nothing went wrong. + */ + if (linked) + validate_ir_tree(linked->ir); +#endif + /* Make a pass over all variable declarations to ensure that arrays with * unspecified sizes have a size specified. The size is inferred from the * max_array_access field. diff --git a/mesalib/src/glsl/opt_dead_functions.cpp b/mesalib/src/glsl/opt_dead_functions.cpp index 3c3eb8904..51c77e3b9 100644 --- a/mesalib/src/glsl/opt_dead_functions.cpp +++ b/mesalib/src/glsl/opt_dead_functions.cpp @@ -1,164 +1,155 @@ -/* - * 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 opt_dead_functions.cpp - * - * Eliminates unused functions from the linked program. - */ - -#include "ir.h" -#include "ir_visitor.h" -#include "ir_expression_flattening.h" -#include "glsl_types.h" - -class signature_entry : public exec_node -{ -public: - signature_entry(ir_function_signature *sig) - { - this->signature = sig; - this->used = false; - } - - ir_function_signature *signature; - bool used; -}; - -class ir_dead_functions_visitor : public ir_hierarchical_visitor { -public: - ir_dead_functions_visitor() - { - this->mem_ctx = ralloc_context(NULL); - this->seen_another_function_signature = false; - } - - ~ir_dead_functions_visitor() - { - ralloc_free(this->mem_ctx); - } - - virtual ir_visitor_status visit_enter(ir_function_signature *); - virtual ir_visitor_status visit_enter(ir_call *); - - signature_entry *get_signature_entry(ir_function_signature *var); - - bool (*predicate)(ir_instruction *ir); - - bool seen_another_function_signature; - - /* List of signature_entry */ - exec_list signature_list; - void *mem_ctx; -}; - - -signature_entry * -ir_dead_functions_visitor::get_signature_entry(ir_function_signature *sig) -{ - foreach_iter(exec_list_iterator, iter, this->signature_list) { - signature_entry *entry = (signature_entry *)iter.get(); - if (entry->signature == sig) - return entry; - } - - signature_entry *entry = new(mem_ctx) signature_entry(sig); - this->signature_list.push_tail(entry); - return entry; -} - - -ir_visitor_status -ir_dead_functions_visitor::visit_enter(ir_function_signature *ir) -{ - signature_entry *entry = this->get_signature_entry(ir); - - if (strcmp(ir->function_name(), "main") == 0) { - entry->used = true; - } - - /* If this is the first signature to look at, no need to descend to see - * if it has calls to another function signature. - */ - if (!this->seen_another_function_signature) { - this->seen_another_function_signature = true; - return visit_continue_with_parent; - } - - return visit_continue; -} - - -ir_visitor_status -ir_dead_functions_visitor::visit_enter(ir_call *ir) -{ - signature_entry *entry = this->get_signature_entry(ir->get_callee()); - - entry->used = true; - - return visit_continue; -} - -bool -do_dead_functions(exec_list *instructions) -{ - ir_dead_functions_visitor v; - bool progress = false; - - visit_list_elements(&v, instructions); - - /* Now that we've figured out which function signatures are used, remove - * the unused ones, and remove function definitions that have no more - * signatures. - */ - foreach_iter(exec_list_iterator, iter, v.signature_list) { - signature_entry *entry = (signature_entry *)iter.get(); - - if (!entry->used) { - entry->signature->remove(); - delete entry->signature; - progress = true; - } - delete(entry); - } - - /* We don't just do this above when we nuked a signature because of - * const pointers. - */ - foreach_iter(exec_list_iterator, iter, *instructions) { - ir_instruction *ir = (ir_instruction *)iter.get(); - ir_function *func = ir->as_function(); - - if (func && func->signatures.is_empty()) { - /* At this point (post-linking), the symbol table is no - * longer in use, so not removing the function from the - * symbol table should be OK. - */ - func->remove(); - delete func; - progress = true; - } - } - - return progress; -} +/* + * 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 opt_dead_functions.cpp + * + * Eliminates unused functions from the linked program. + */ + +#include "ir.h" +#include "ir_visitor.h" +#include "ir_expression_flattening.h" +#include "glsl_types.h" + +class signature_entry : public exec_node +{ +public: + signature_entry(ir_function_signature *sig) + { + this->signature = sig; + this->used = false; + } + + ir_function_signature *signature; + bool used; +}; + +class ir_dead_functions_visitor : public ir_hierarchical_visitor { +public: + ir_dead_functions_visitor() + { + this->mem_ctx = ralloc_context(NULL); + } + + ~ir_dead_functions_visitor() + { + ralloc_free(this->mem_ctx); + } + + virtual ir_visitor_status visit_enter(ir_function_signature *); + virtual ir_visitor_status visit_enter(ir_call *); + + signature_entry *get_signature_entry(ir_function_signature *var); + + bool (*predicate)(ir_instruction *ir); + + /* List of signature_entry */ + exec_list signature_list; + void *mem_ctx; +}; + + +signature_entry * +ir_dead_functions_visitor::get_signature_entry(ir_function_signature *sig) +{ + foreach_iter(exec_list_iterator, iter, this->signature_list) { + signature_entry *entry = (signature_entry *)iter.get(); + if (entry->signature == sig) + return entry; + } + + signature_entry *entry = new(mem_ctx) signature_entry(sig); + this->signature_list.push_tail(entry); + return entry; +} + + +ir_visitor_status +ir_dead_functions_visitor::visit_enter(ir_function_signature *ir) +{ + signature_entry *entry = this->get_signature_entry(ir); + + if (strcmp(ir->function_name(), "main") == 0) { + entry->used = true; + } + + + + return visit_continue; +} + + +ir_visitor_status +ir_dead_functions_visitor::visit_enter(ir_call *ir) +{ + signature_entry *entry = this->get_signature_entry(ir->get_callee()); + + entry->used = true; + + return visit_continue; +} + +bool +do_dead_functions(exec_list *instructions) +{ + ir_dead_functions_visitor v; + bool progress = false; + + visit_list_elements(&v, instructions); + + /* Now that we've figured out which function signatures are used, remove + * the unused ones, and remove function definitions that have no more + * signatures. + */ + foreach_iter(exec_list_iterator, iter, v.signature_list) { + signature_entry *entry = (signature_entry *)iter.get(); + + if (!entry->used) { + entry->signature->remove(); + delete entry->signature; + progress = true; + } + delete(entry); + } + + /* We don't just do this above when we nuked a signature because of + * const pointers. + */ + foreach_iter(exec_list_iterator, iter, *instructions) { + ir_instruction *ir = (ir_instruction *)iter.get(); + ir_function *func = ir->as_function(); + + if (func && func->signatures.is_empty()) { + /* At this point (post-linking), the symbol table is no + * longer in use, so not removing the function from the + * symbol table should be OK. + */ + func->remove(); + delete func; + progress = true; + } + } + + return progress; +} -- cgit v1.2.3