From 703ad42c809400c0ad837a961bd8e477dd6a6342 Mon Sep 17 00:00:00 2001 From: hubicka Date: Fri, 16 May 2014 17:49:06 +0000 Subject: [PATCH] * varpool.c (dump_varpool_node): Dump write-only flag. * lto-cgraph.c (lto_output_varpool_node, input_varpool_node): Stream write-only flag. * tree-cfg.c (execute_fixup_cfg): Remove statements setting write-only variables. * gcc.c-torture/execute/20101011-1.c: Update testcase. * gcc.dg/ira-shrinkwrap-prep-1.c: Update testcase. * gcc.dg/tree-ssa/writeonly.c: New testcase. * gcc.dg/tree-ssa/ssa-dse-6.c: Update testcase. * gcc.dg/tree-ssa/pr21559.c: Update testcase. * gcc.dg/debug/pr35154.c: Update testcase. * gcc.target/i386/vectorize1.c: Update testcase. * ipa.c (process_references): New function. (set_readonly_bit): New function. (set_writeonly_bit): New function. (clear_addressable_bit): New function. (ipa_discover_readonly_nonaddressable_var): Mark write only variables; fix handling of aliases. * cgraph.h (struct varpool_node): Add writeonly flag. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@210522 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 ++ gcc/cgraph.h | 2 + gcc/ipa.c | 114 ++++++++++++++++++----- gcc/lto-cgraph.c | 2 + gcc/testsuite/ChangeLog | 17 ++++ gcc/testsuite/gcc.c-torture/execute/20101011-1.c | 2 +- gcc/testsuite/gcc.dg/debug/pr35154.c | 3 +- gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/pr21559.c | 1 + gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c | 1 + gcc/testsuite/gcc.dg/tree-ssa/writeonly.c | 20 ++++ gcc/testsuite/gcc.target/i386/vectorize1.c | 1 + gcc/tree-cfg.c | 39 +++++++- gcc/varpool.c | 2 + 14 files changed, 186 insertions(+), 27 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/writeonly.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4477e8c6e893..f899ba15db7e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2014-05-16 Jan Hubicka + + * varpool.c (dump_varpool_node): Dump write-only flag. + * lto-cgraph.c (lto_output_varpool_node, input_varpool_node): Stream + write-only flag. + * tree-cfg.c (execute_fixup_cfg): Remove statements setting write-only variables. + 2014-05-16 Vladimir Makarov PR rtl-optimization/60969 diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 84fc1d90536d..a29a31c4b67a 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -76,6 +76,8 @@ public: /* Set once the definition was analyzed. The list of references and other properties are built during analysis. */ unsigned analyzed : 1; + /* Set for write-only variables. */ + unsigned writeonly : 1; /*** Visibility and linkage flags. ***/ diff --git a/gcc/ipa.c b/gcc/ipa.c index a14f02418201..da424914ce97 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -624,6 +624,77 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) return changed; } +/* Process references to VNODE and set flags WRITTEN, ADDRESS_TAKEN, READ + as needed, also clear EXPLICIT_REFS if the references to given variable + do not need to be explicit. */ + +void +process_references (varpool_node *vnode, + bool *written, bool *address_taken, + bool *read, bool *explicit_refs) +{ + int i; + struct ipa_ref *ref; + + if (!varpool_all_refs_explicit_p (vnode) + || TREE_THIS_VOLATILE (vnode->decl)) + *explicit_refs = false; + + for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list, + i, ref) + && *explicit_refs && (!*written || !*address_taken || !*read); i++) + switch (ref->use) + { + case IPA_REF_ADDR: + *address_taken = true; + break; + case IPA_REF_LOAD: + *read = true; + break; + case IPA_REF_STORE: + *written = true; + break; + case IPA_REF_ALIAS: + process_references (varpool (ref->referring), written, address_taken, + read, explicit_refs); + break; + } +} + +/* Set TREE_READONLY bit. */ + +bool +set_readonly_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED) +{ + TREE_READONLY (vnode->decl) = true; + return false; +} + +/* Set writeonly bit and clear the initalizer, since it will not be needed. */ + +bool +set_writeonly_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED) +{ + vnode->writeonly = true; + if (optimize) + { + DECL_INITIAL (vnode->decl) = NULL; + if (!vnode->alias) + ipa_remove_all_references (&vnode->ref_list); + } + return false; +} + +/* Clear addressale bit of VNODE. */ + +bool +clear_addressable_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED) +{ + vnode->address_taken = false; + TREE_ADDRESSABLE (vnode->decl) = 0; + return false; +} + /* Discover variables that have no longer address taken or that are read only and update their flags. @@ -640,43 +711,40 @@ ipa_discover_readonly_nonaddressable_vars (void) if (dump_file) fprintf (dump_file, "Clearing variable flags:"); FOR_EACH_VARIABLE (vnode) - if (vnode->definition && varpool_all_refs_explicit_p (vnode) + if (!vnode->alias && (TREE_ADDRESSABLE (vnode->decl) + || !vnode->writeonly || !TREE_READONLY (vnode->decl))) { bool written = false; bool address_taken = false; - int i; - struct ipa_ref *ref; - for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list, - i, ref) - && (!written || !address_taken); i++) - switch (ref->use) - { - case IPA_REF_ADDR: - address_taken = true; - break; - case IPA_REF_LOAD: - break; - case IPA_REF_STORE: - written = true; - break; - } - if (TREE_ADDRESSABLE (vnode->decl) && !address_taken) + bool read = false; + bool explicit_refs = true; + + process_references (vnode, &written, &address_taken, &read, &explicit_refs); + if (!explicit_refs) + continue; + if (!address_taken) { - if (dump_file) + if (TREE_ADDRESSABLE (vnode->decl) && dump_file) fprintf (dump_file, " %s (addressable)", vnode->name ()); - TREE_ADDRESSABLE (vnode->decl) = 0; + varpool_for_node_and_aliases (vnode, clear_addressable_bit, NULL, true); } - if (!TREE_READONLY (vnode->decl) && !address_taken && !written + if (!address_taken && !written /* Making variable in explicit section readonly can cause section type conflict. See e.g. gcc.c-torture/compile/pr23237.c */ && DECL_SECTION_NAME (vnode->decl) == NULL) { - if (dump_file) + if (!TREE_READONLY (vnode->decl) && dump_file) fprintf (dump_file, " %s (read-only)", vnode->name ()); - TREE_READONLY (vnode->decl) = 1; + varpool_for_node_and_aliases (vnode, set_readonly_bit, NULL, true); + } + if (!vnode->writeonly && !read && !address_taken) + { + if (dump_file) + fprintf (dump_file, " %s (write-only)", vnode->name ()); + varpool_for_node_and_aliases (vnode, set_writeonly_bit, NULL, true); } } if (dump_file) diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 121614a9428f..b22eb46ac3e7 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -562,6 +562,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node, bp_pack_value (&bp, node->forced_by_abi, 1); bp_pack_value (&bp, node->unique_name, 1); bp_pack_value (&bp, node->body_removed, 1); + bp_pack_value (&bp, node->writeonly, 1); bp_pack_value (&bp, node->definition, 1); alias_p = node->alias && (!boundary_p || node->weakref); bp_pack_value (&bp, alias_p, 1); @@ -1153,6 +1154,7 @@ input_varpool_node (struct lto_file_decl_data *file_data, node->forced_by_abi = bp_unpack_value (&bp, 1); node->unique_name = bp_unpack_value (&bp, 1); node->body_removed = bp_unpack_value (&bp, 1); + node->writeonly = bp_unpack_value (&bp, 1); node->definition = bp_unpack_value (&bp, 1); node->alias = bp_unpack_value (&bp, 1); node->weakref = bp_unpack_value (&bp, 1); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0b1d90505328..5aee09ad14c5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,20 @@ +2014-05-16 Jan Hubicka + + * gcc.c-torture/execute/20101011-1.c: Update testcase. + * gcc.dg/ira-shrinkwrap-prep-1.c: Update testcase. + * gcc.dg/tree-ssa/writeonly.c: New testcase. + * gcc.dg/tree-ssa/ssa-dse-6.c: Update testcase. + * gcc.dg/tree-ssa/pr21559.c: Update testcase. + * gcc.dg/debug/pr35154.c: Update testcase. + * gcc.target/i386/vectorize1.c: Update testcase. + * ipa.c (process_references): New function. + (set_readonly_bit): New function. + (set_writeonly_bit): New function. + (clear_addressable_bit): New function. + (ipa_discover_readonly_nonaddressable_var): Mark write only variables; fix + handling of aliases. + * cgraph.h (struct varpool_node): Add writeonly flag. + 2014-05-16 Paolo Carlini PR c++/51640 diff --git a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c index 1c0ee6d87b64..9299bb9205a8 100644 --- a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c @@ -92,7 +92,7 @@ sigfpe (int signum __attribute__ ((unused))) eliminate the assignment to the global k. */ static int i; static int j; -int k; +int k __attribute__ ((used)); int main () diff --git a/gcc/testsuite/gcc.dg/debug/pr35154.c b/gcc/testsuite/gcc.dg/debug/pr35154.c index fa658be2cbec..7f6a6eaa0ecd 100644 --- a/gcc/testsuite/gcc.dg/debug/pr35154.c +++ b/gcc/testsuite/gcc.dg/debug/pr35154.c @@ -2,6 +2,7 @@ proper structure. These should be lettered G for the struct that gives the name to the .comm, and should be V or S for .lcomm symbols. */ +__attribute__ ((used)) static char i_outer; struct { char f1; @@ -15,7 +16,7 @@ struct { int main() { - static char i_inner[2]; + static char i_inner[2] __attribute__ ((used)); i_inner[0] = 'a'; i_inner[1] = 'b'; opta.f1 = 'c'; opta.f2 = 'd'; diff --git a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c index 54d3e7615733..171a2bd5e174 100644 --- a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c +++ b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c @@ -7,7 +7,7 @@ foo (long a) return a + 5; } -static long g; +static long g __attribute__ ((used)); long __attribute__((noinline, noclone)) bar (long a) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c index 6378d1aa729c..a991e0490358 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c @@ -9,6 +9,7 @@ void foo (void) { int toread; int bytes; + __attribute__ ((used)) static char eof_reached = 0; toread = blocksize; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c index 3d020067ca7d..cf496291f8dd 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c @@ -3,6 +3,7 @@ int foo11 (int c) { + __attribute__ ((used)) static int local1, local2; local1 = 0; local2 += c; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/writeonly.c b/gcc/testsuite/gcc.dg/tree-ssa/writeonly.c new file mode 100644 index 000000000000..156cf3ef6a8d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/writeonly.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ +static struct a {int magic1,b;} a; +volatile int magic2; +static struct b {int a,b,c,d,e,f;} magic3; + +struct b foo(); + +t() +{ + a.magic1 = 1; + magic2 = 1; + magic3 = foo(); +} +/* { dg-final { scan-tree-dump-not "magic1" "optimized"} } */ +/* { dg-final { scan-tree-dump-not "magic3" "optimized"} } */ +/* { dg-final { scan-tree-dump "magic2" "optimized"} } */ +/* { dg-final { scan-tree-dump "foo" "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/i386/vectorize1.c b/gcc/testsuite/gcc.target/i386/vectorize1.c index f673e44c9639..974ffd82628c 100644 --- a/gcc/testsuite/gcc.target/i386/vectorize1.c +++ b/gcc/testsuite/gcc.target/i386/vectorize1.c @@ -10,6 +10,7 @@ typedef struct int set_names (void) { + __attribute__ ((used)) static tx_typ tt1; int ln; for (ln = 0; ln < 8; ln++) diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index fee1ede809e9..9228d41970cc 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -8431,7 +8431,7 @@ execute_fixup_cfg (void) FOR_EACH_BB_FN (bb, cfun) { bb->count = apply_scale (bb->count, count_scale); - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);) { gimple stmt = gsi_stmt (gsi); tree decl = is_gimple_call (stmt) @@ -8457,9 +8457,46 @@ execute_fixup_cfg (void) todo |= TODO_cleanup_cfg; } + /* Remove stores to variables we marked write-only. + Keep access when store has side effect, i.e. in case when source + is volatile. */ + if (gimple_store_p (stmt) + && !gimple_has_side_effects (stmt)) + { + tree lhs = get_base_address (gimple_get_lhs (stmt)); + + if (TREE_CODE (lhs) == VAR_DECL + && (TREE_STATIC (lhs) || DECL_EXTERNAL (lhs)) + && varpool_get_node (lhs)->writeonly) + { + unlink_stmt_vdef (stmt); + gsi_remove (&gsi, true); + release_defs (stmt); + todo |= TODO_update_ssa | TODO_cleanup_cfg; + continue; + } + } + /* For calls we can simply remove LHS when it is known + to be write-only. */ + if (is_gimple_call (stmt) + && gimple_get_lhs (stmt)) + { + tree lhs = get_base_address (gimple_get_lhs (stmt)); + + if (TREE_CODE (lhs) == VAR_DECL + && (TREE_STATIC (lhs) || DECL_EXTERNAL (lhs)) + && varpool_get_node (lhs)->writeonly) + { + gimple_call_set_lhs (stmt, NULL); + update_stmt (stmt); + todo |= TODO_update_ssa | TODO_cleanup_cfg; + } + } + if (maybe_clean_eh_stmt (stmt) && gimple_purge_dead_eh_edges (bb)) todo |= TODO_cleanup_cfg; + gsi_next (&gsi); } FOR_EACH_EDGE (e, ei, bb->succs) diff --git a/gcc/varpool.c b/gcc/varpool.c index 69172c69dbae..c4fd11c2946e 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -211,6 +211,8 @@ dump_varpool_node (FILE *f, varpool_node *node) fprintf (f, " read-only"); if (ctor_for_folding (node->decl) != error_mark_node) fprintf (f, " const-value-known"); + if (node->writeonly) + fprintf (f, " write-only"); fprintf (f, "\n"); } -- 2.11.4.GIT