diff options
author | Ian Lance Taylor <iant@google.com> | 2011-01-26 01:26:48 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-01-26 01:26:48 +0000 |
commit | 744f0946bcbf7be92a725383d41c31673849efa9 (patch) | |
tree | 40f04bab603217a17801c186064a864353aa2c57 /gcc/c-decl.c | |
parent | 70187f017bf392594f209a7434b82518c34ff00b (diff) | |
download | gcc-744f0946bcbf7be92a725383d41c31673849efa9.zip gcc-744f0946bcbf7be92a725383d41c31673849efa9.tar.gz gcc-744f0946bcbf7be92a725383d41c31673849efa9.tar.bz2 |
re PR tree-optimization/26854 (Inordinate compile times on large routines)
PR tree-optimization/26854
* c-decl.c (struct c_scope): Add field has_jump_unsafe_decl.
(decl_jump_unsafe): Move higher in file, with no other change.
(bind): Set has_jump_unsafe_decl if appropriate.
(update_label_decls): Test has_jump_unsafe_decl to avoid loop.
(check_earlier_gotos): Likewise.
(c_check_switch_jump_warnings): Likewise.
From-SVN: r169267
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r-- | gcc/c-decl.c | 119 |
1 files changed, 74 insertions, 45 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 4d24c60..b438b06 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -404,6 +404,13 @@ struct GTY((chain_next ("%h.outer"))) c_scope { up searching for labels when popping scopes, particularly since labels are normally only found at function scope. */ BOOL_BITFIELD has_label_bindings : 1; + + /* True if we should issue a warning if a goto statement crosses any + of the bindings. We still need to check the list of bindings to + find the specific ones we need to warn about. This is true if + decl_jump_unsafe would return true for any of the bindings. This + is used to avoid looping over all the bindings unnecessarily. */ + BOOL_BITFIELD has_jump_unsafe_decl : 1; }; /* The scope currently in effect. */ @@ -554,6 +561,31 @@ add_stmt (tree t) return t; } +/* Return true if we will want to say something if a goto statement + crosses DECL. */ + +static bool +decl_jump_unsafe (tree decl) +{ + if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node) + return false; + + /* Always warn about crossing variably modified types. */ + if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL) + && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE)) + return true; + + /* Otherwise, only warn if -Wgoto-misses-init and this is an + initialized automatic decl. */ + if (warn_jump_misses_init + && TREE_CODE (decl) == VAR_DECL + && !TREE_STATIC (decl) + && DECL_INITIAL (decl) != NULL_TREE) + return true; + + return false; +} + void c_print_identifier (FILE *file, tree node, int indent) @@ -602,6 +634,9 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible, b->prev = scope->bindings; scope->bindings = b; + if (decl_jump_unsafe (decl)) + scope->has_jump_unsafe_decl = 1; + if (!name) return; @@ -758,31 +793,6 @@ set_spot_bindings (struct c_spot_bindings *p, bool defining) p->left_stmt_expr = false; } -/* Return true if we will want to say something if a goto statement - crosses DECL. */ - -static bool -decl_jump_unsafe (tree decl) -{ - if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node) - return false; - - /* Always warn about crossing variably modified types. */ - if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL) - && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE)) - return true; - - /* Otherwise, only warn if -Wgoto-misses-init and this is an - initialized automatic decl. */ - if (warn_jump_misses_init - && TREE_CODE (decl) == VAR_DECL - && !TREE_STATIC (decl) - && DECL_INITIAL (decl) != NULL_TREE) - return true; - - return false; -} - /* Update spot bindings P as we pop out of SCOPE. Return true if we should push decls for a label. */ @@ -969,6 +979,7 @@ update_label_decls (struct c_scope *scope) { struct c_label_vars *label_vars; struct c_binding *b1; + bool hjud; unsigned int ix; struct c_goto_bindings *g; @@ -977,18 +988,26 @@ update_label_decls (struct c_scope *scope) label_vars = b->u.label; b1 = label_vars->label_bindings.bindings_in_scope; + if (label_vars->label_bindings.scope == NULL) + hjud = false; + else + hjud = label_vars->label_bindings.scope->has_jump_unsafe_decl; if (update_spot_bindings (scope, &label_vars->label_bindings)) { /* This label is defined in this scope. */ - for (; b1 != NULL; b1 = b1->prev) + if (hjud) { - /* A goto from later in the function to this - label will never see the initialization of - B1, if any. Save it to issue a warning if - needed. */ - if (decl_jump_unsafe (b1->decl)) - VEC_safe_push (tree, gc, label_vars->decls_in_scope, - b1->decl); + for (; b1 != NULL; b1 = b1->prev) + { + /* A goto from later in the function to this + label will never see the initialization + of B1, if any. Save it to issue a + warning if needed. */ + if (decl_jump_unsafe (b1->decl)) + VEC_safe_push (tree, gc, + label_vars->decls_in_scope, + b1->decl); + } } } @@ -3165,12 +3184,15 @@ check_earlier_gotos (tree label, struct c_label_vars* label_vars) /* We have a goto to this label. The goto is going forward. In g->scope, the goto is going to skip any binding which was defined after g->bindings_in_scope. */ - for (b = g->goto_bindings.scope->bindings; - b != g->goto_bindings.bindings_in_scope; - b = b->prev) + if (g->goto_bindings.scope->has_jump_unsafe_decl) { - if (decl_jump_unsafe (b->decl)) - warn_about_goto (g->loc, label, b->decl); + for (b = g->goto_bindings.scope->bindings; + b != g->goto_bindings.bindings_in_scope; + b = b->prev) + { + if (decl_jump_unsafe (b->decl)) + warn_about_goto (g->loc, label, b->decl); + } } /* We also need to warn about decls defined in any scopes @@ -3180,14 +3202,17 @@ check_earlier_gotos (tree label, struct c_label_vars* label_vars) scope = scope->outer) { gcc_assert (scope != NULL); - if (scope == label_vars->label_bindings.scope) - b = label_vars->label_bindings.bindings_in_scope; - else - b = scope->bindings; - for (; b != NULL; b = b->prev) + if (scope->has_jump_unsafe_decl) { - if (decl_jump_unsafe (b->decl)) - warn_about_goto (g->loc, label, b->decl); + if (scope == label_vars->label_bindings.scope) + b = label_vars->label_bindings.bindings_in_scope; + else + b = scope->bindings; + for (; b != NULL; b = b->prev) + { + if (decl_jump_unsafe (b->decl)) + warn_about_goto (g->loc, label, b->decl); + } } } @@ -3303,6 +3328,10 @@ c_check_switch_jump_warnings (struct c_spot_bindings *switch_bindings, struct c_binding *b; gcc_assert (scope != NULL); + + if (!scope->has_jump_unsafe_decl) + continue; + for (b = scope->bindings; b != NULL; b = b->prev) { if (decl_jump_unsafe (b->decl)) |