From ce91e74c187986865c3de8fbd871242183afa93d Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Fri, 24 Jun 2005 17:14:04 +0200 Subject: [PATCH] tree-optimize.c (init_tree_optimization_passes): Fix flags of all_passes and all_ipa_passes. * tree-optimize.c (init_tree_optimization_passes): Fix flags of all_passes and all_ipa_passes. * c-common.c: Include cgraph.h (handle_externally_visible_attribute): New function. (c_common_att): Add "externally_visible" attribute. * cgraph.c (decide_is_variable_needed): Obey externally visible flag. (cgraph_varpool_finalize_decl): Avoid redundant checking. * cgraph.h (struct cgraph_node): New flag externally_visible. (decide_is_function_needed): Obey externally visible flag. (cgraph_finalize_function): Avoid redundant checks. (cgraph_function_and_variable_visibility): Bring symbols local when asked for. * common.opt (fwhole-program): New flag. * doc/invoke.texi (-fwhole-program): Document. From-SVN: r101295 --- gcc/ChangeLog | 20 +++++++++++ gcc/c-common.c | 46 ++++++++++++++++++++++++++ gcc/cgraph.c | 5 +-- gcc/cgraph.h | 2 ++ gcc/cgraphunit.c | 27 ++++++++++++--- gcc/common.opt | 4 +++ gcc/doc/extend.texi | 9 ++++- gcc/doc/invoke.texi | 15 ++++++++- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-1.c | 23 +++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-2.c | 8 +++++ 11 files changed, 156 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-1.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 818aea5..f1c680c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2005-06-24 Jan Hubicka + + * tree-optimize.c (init_tree_optimization_passes): Fix flags of + all_passes and all_ipa_passes. + + * c-common.c: Include cgraph.h + (handle_externally_visible_attribute): New function. + (c_common_att): Add "externally_visible" attribute. + * cgraph.c (decide_is_variable_needed): Obey externally + visible flag. + (cgraph_varpool_finalize_decl): Avoid redundant checking. + * cgraph.h (struct cgraph_node): New flag externally_visible. + (decide_is_function_needed): Obey externally visible flag. + (cgraph_finalize_function): Avoid redundant checks. + (cgraph_function_and_variable_visibility): Bring symbols local + when asked for. + * common.opt (fwhole-program): New flag. + + * doc/invoke.texi (-fwhole-program): Document. + 2005-06-24 Mark Mitchell PR 22171 diff --git a/gcc/c-common.c b/gcc/c-common.c index b7263aa..c9ebb58 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -47,6 +47,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "tree-mudflap.h" #include "opts.h" #include "real.h" +#include "cgraph.h" cpp_reader *parse_in; /* Declared in c-pragma.h. */ @@ -514,6 +515,8 @@ static tree handle_always_inline_attribute (tree *, tree, tree, int, bool *); static tree handle_used_attribute (tree *, tree, tree, int, bool *); static tree handle_unused_attribute (tree *, tree, tree, int, bool *); +static tree handle_externally_visible_attribute (tree *, tree, tree, int, + bool *); static tree handle_const_attribute (tree *, tree, tree, int, bool *); static tree handle_transparent_union_attribute (tree *, tree, tree, int, bool *); @@ -580,6 +583,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_used_attribute }, { "unused", 0, 0, false, false, false, handle_unused_attribute }, + { "externally_visible", 0, 0, true, false, false, + handle_externally_visible_attribute }, /* The same comments as for noreturn attributes apply to const ones. */ { "const", 0, 0, true, false, false, handle_const_attribute }, @@ -4129,6 +4134,47 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args), return NULL_TREE; } +/* Handle a "externally_visible" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_externally_visible_attribute (tree *pnode, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree node = *pnode; + + if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL) + || !TREE_PUBLIC (node)) + { + warning (OPT_Wattributes, + "%qE attribute have effect only on public objects", name); + *no_add_attrs = true; + } + else if (TREE_CODE (node) == FUNCTION_DECL) + { + struct cgraph_node *n = cgraph_node (node); + n->local.externally_visible = true; + if (n->local.finalized) + cgraph_mark_needed_node (n); + } + else if (TREE_CODE (node) == VAR_DECL) + { + struct cgraph_varpool_node *n = cgraph_varpool_node (node); + n->externally_visible = true; + if (n->finalized) + cgraph_varpool_mark_needed_node (n); + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + /* Handle a "const" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/cgraph.c b/gcc/cgraph.c index b9b1b14..af84ebf 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -807,7 +807,8 @@ bool decide_is_variable_needed (struct cgraph_varpool_node *node, tree decl) { /* If the user told us it is used, then it must be so. */ - if (lookup_attribute ("used", DECL_ATTRIBUTES (decl))) + if (node->externally_visible + || lookup_attribute ("used", DECL_ATTRIBUTES (decl))) return true; /* ??? If the assembler name is set by hand, it is possible to assemble @@ -863,7 +864,7 @@ cgraph_varpool_finalize_decl (tree decl) /* Since we reclaim unreachable nodes at the end of every language level unit, we need to be conservative about possible entry points there. */ - if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) + else if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) cgraph_varpool_mark_needed_node (node); if (cgraph_global_info_ready || !flag_unit_at_a_time) cgraph_varpool_assemble_pending_decls (); diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 9406e09..9b7306b 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -159,6 +159,8 @@ struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) bool analyzed; /* Set when function is scheduled to be assembled. */ bool output; + /* Set when function is visible by other units. */ + bool externally_visible; /* Set for aliases once they got through assemble_alias. */ bool alias; }; diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 2f993f3..f3d718d 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -189,9 +189,16 @@ static bool decide_is_function_needed (struct cgraph_node *node, tree decl) { tree origin; + if (MAIN_NAME_P (DECL_NAME (decl)) + && TREE_PUBLIC (decl)) + { + node->local.externally_visible = true; + return true; + } /* If the user told us it is used, then it must be so. */ - if (lookup_attribute ("used", DECL_ATTRIBUTES (decl))) + if (node->local.externally_visible + || lookup_attribute ("used", DECL_ATTRIBUTES (decl))) return true; /* ??? If the assembler name is set by hand, it is possible to assemble @@ -209,7 +216,8 @@ decide_is_function_needed (struct cgraph_node *node, tree decl) /* Externally visible functions must be output. The exception is COMDAT functions that must be output only when they are needed. */ - if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) + if ((TREE_PUBLIC (decl) && !flag_whole_program) + && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) return true; /* Constructors and destructors are reachable from the runtime by @@ -428,7 +436,7 @@ cgraph_finalize_function (tree decl, bool nested) /* Since we reclaim unreachable nodes at the end of every language level unit, we need to be conservative about possible entry points there. */ - if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) + if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))) cgraph_mark_reachable_node (node); /* If not unit at a time, go ahead and emit everything we've found @@ -1059,7 +1067,13 @@ cgraph_function_and_variable_visibility (void) if (node->reachable && (DECL_COMDAT (node->decl) || (TREE_PUBLIC (node->decl) && !DECL_EXTERNAL (node->decl)))) - node->local.externally_visible = 1; + node->local.externally_visible = true; + if (!node->local.externally_visible && node->analyzed + && !DECL_EXTERNAL (node->decl)) + { + gcc_assert (flag_whole_program || !TREE_PUBLIC (node->decl)); + TREE_PUBLIC (node->decl) = 0; + } node->local.local = (!node->needed && node->analyzed && !DECL_EXTERNAL (node->decl) @@ -1070,6 +1084,11 @@ cgraph_function_and_variable_visibility (void) if (vnode->needed && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl))) vnode->externally_visible = 1; + if (!vnode->externally_visible) + { + gcc_assert (flag_whole_program || !TREE_PUBLIC (vnode->decl)); + TREE_PUBLIC (vnode->decl) = 0; + } gcc_assert (TREE_STATIC (vnode->decl)); } diff --git a/gcc/common.opt b/gcc/common.opt index f54eabc..f1e27d5 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -986,6 +986,10 @@ fweb Common Report Var(flag_web) Init(0) Construct webs and split unrelated uses of single variable +fwhole-program +Common Report Var(flag_whole_program) Init(0) +Perform whole program optimizations + fwrapv Common Report Var(flag_wrapv) Assume signed arithmetic overflow wraps around diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 6a31e9c..c0363dd 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1525,7 +1525,8 @@ attributes are currently defined for functions on all targets: @code{format}, @code{format_arg}, @code{no_instrument_function}, @code{section}, @code{constructor}, @code{destructor}, @code{used}, @code{unused}, @code{deprecated}, @code{weak}, @code{malloc}, -@code{alias}, @code{warn_unused_result} and @code{nonnull}. Several other +@code{alias}, @code{warn_unused_result}, @code{nonnull} +and @code{externally_visible}. Several other attributes are defined for functions on particular target systems. Other attributes, including @code{section} are supported for variables declarations (@pxref{Variable Attributes}) and for types (@pxref{Type Attributes}). @@ -2345,6 +2346,12 @@ also be used with non-function declarations. Weak symbols are supported for ELF targets, and also for a.out targets when using the GNU assembler and linker. +@item externally_visible +@cindex @code{externally_visible} attribute. +This attribute, attached to a global variable or function nullify +effect of @option{-fwhole-program} command line option, so the object +remain visible outside the current compilation unit + @end table You can specify multiple attributes in a declaration by separating them diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index ebb783e..4e229b0 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -335,7 +335,7 @@ Objective-C and Objective-C++ Dialects}. -ftree-dominator-opts -ftree-dse -ftree-copyrename -ftree-sink @gol -ftree-ch -ftree-sra -ftree-ter -ftree-lrs -ftree-fre -ftree-vectorize @gol -ftree-salias -fweb @gol --ftree-copy-prop -ftree-store-ccp -ftree-store-copy-prop @gol +-ftree-copy-prop -ftree-store-ccp -ftree-store-copy-prop -fwhole-program @gol --param @var{name}=@var{value} -O -O0 -O1 -O2 -O3 -Os} @@ -5256,6 +5256,19 @@ Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}, on targets where the default format for debugging information supports variable tracking. +@item -fwhole-program +@opindex fwhole-program +Assume that the current compilation unit represents whole program being +compiled. All public functions and variables with the exception of @code{main} +and those marged by attribute @code{externally_visible} become static functions +and in a affect gets more aggresively optimized by interprocedural optimizers. +While this option is equivalent to proper use of @code{static} keyword for +programs consitsting of single file, in combination with option +@option{--combine} this flag can be used to compile most of smaller scale C +programs since the functions and variables become local for the whole combined +compilation unit, not for the single source file itself. + + @item -fno-cprop-registers @opindex fno-cprop-registers After register allocation and post-register allocation instruction splitting, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f699cd2..503bb09 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-06-22 Jan Hubicka + + * wholeprogram-1.c: New testcase. + * wholeprogram-2.c: New testcase. + 2005-06-24 Mark Mitchell PR 22171 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-1.c b/gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-1.c new file mode 100644 index 0000000..9d0af1f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-1.c @@ -0,0 +1,23 @@ +/* { dg-options "-O2 -fdump-tree-optimized -fwhole-program" } */ +int b[100]; +void abort (void); + +void +large_function () +{ + int i; + for (i = 0; i < 99; i++) + if (b[i] / (b[i+1] + 1)) + abort (); +} + +main () +{ + large_function (); +} + +/* Function should be inlined as called once. */ +/* { dg-final { scan-tree-dump-not "large_function" "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-2.c b/gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-2.c new file mode 100644 index 0000000..bbdd0dd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-2.c @@ -0,0 +1,8 @@ +/* { dg-options "-O2 -fdump-tree-optimized -fwhole-program" } */ +__attribute__ ((externally_visible)) +void +externally_visible_function () +{ +} +/* { dg-final { scan-tree-dump "externally_visible_function" "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ -- 2.7.4