* 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
+2014-05-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * 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 <vmakarov@redhat.com>
PR rtl-optimization/60969
/* 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. ***/
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.
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)
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);
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);
+2014-05-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * 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 <paolo.carlini@oracle.com>
PR c++/51640
eliminate the assignment to the global k. */
static int i;
static int j;
-int k;
+int k __attribute__ ((used));
int
main ()
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;
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';
return a + 5;
}
-static long g;
+static long g __attribute__ ((used));
long __attribute__((noinline, noclone))
bar (long a)
{
int toread;
int bytes;
+ __attribute__ ((used))
static char eof_reached = 0;
toread = blocksize;
int foo11 (int c)
{
+ __attribute__ ((used))
static int local1, local2;
local1 = 0;
local2 += c;
--- /dev/null
+/* { 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" } } */
int set_names (void)
{
+ __attribute__ ((used))
static tx_typ tt1;
int ln;
for (ln = 0; ln < 8; ln++)
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)
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)
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");
}