Commit 6de88c6a by Jan Hubicka Committed by Jan Hubicka

varpool.c (dump_varpool_node): Dump write-only flag.


	* 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.

From-SVN: r210522
parent 54674a35
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> 2014-05-16 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/60969 PR rtl-optimization/60969
......
...@@ -76,6 +76,8 @@ public: ...@@ -76,6 +76,8 @@ public:
/* Set once the definition was analyzed. The list of references and /* Set once the definition was analyzed. The list of references and
other properties are built during analysis. */ other properties are built during analysis. */
unsigned analyzed : 1; unsigned analyzed : 1;
/* Set for write-only variables. */
unsigned writeonly : 1;
/*** Visibility and linkage flags. ***/ /*** Visibility and linkage flags. ***/
......
...@@ -624,6 +624,77 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -624,6 +624,77 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
return changed; 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 /* Discover variables that have no longer address taken or that are read only
and update their flags. and update their flags.
...@@ -640,43 +711,40 @@ ipa_discover_readonly_nonaddressable_vars (void) ...@@ -640,43 +711,40 @@ ipa_discover_readonly_nonaddressable_vars (void)
if (dump_file) if (dump_file)
fprintf (dump_file, "Clearing variable flags:"); fprintf (dump_file, "Clearing variable flags:");
FOR_EACH_VARIABLE (vnode) FOR_EACH_VARIABLE (vnode)
if (vnode->definition && varpool_all_refs_explicit_p (vnode) if (!vnode->alias
&& (TREE_ADDRESSABLE (vnode->decl) && (TREE_ADDRESSABLE (vnode->decl)
|| !vnode->writeonly
|| !TREE_READONLY (vnode->decl))) || !TREE_READONLY (vnode->decl)))
{ {
bool written = false; bool written = false;
bool address_taken = false; bool address_taken = false;
int i; bool read = false;
struct ipa_ref *ref; bool explicit_refs = true;
for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list,
i, ref) process_references (vnode, &written, &address_taken, &read, &explicit_refs);
&& (!written || !address_taken); i++) if (!explicit_refs)
switch (ref->use) continue;
{ if (!address_taken)
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)
{ {
if (dump_file) if (TREE_ADDRESSABLE (vnode->decl) && dump_file)
fprintf (dump_file, " %s (addressable)", vnode->name ()); 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 /* Making variable in explicit section readonly can cause section
type conflict. type conflict.
See e.g. gcc.c-torture/compile/pr23237.c */ See e.g. gcc.c-torture/compile/pr23237.c */
&& DECL_SECTION_NAME (vnode->decl) == NULL) && DECL_SECTION_NAME (vnode->decl) == NULL)
{ {
if (dump_file) if (!TREE_READONLY (vnode->decl) && dump_file)
fprintf (dump_file, " %s (read-only)", vnode->name ()); 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) if (dump_file)
......
...@@ -562,6 +562,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node, ...@@ -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->forced_by_abi, 1);
bp_pack_value (&bp, node->unique_name, 1); bp_pack_value (&bp, node->unique_name, 1);
bp_pack_value (&bp, node->body_removed, 1); bp_pack_value (&bp, node->body_removed, 1);
bp_pack_value (&bp, node->writeonly, 1);
bp_pack_value (&bp, node->definition, 1); bp_pack_value (&bp, node->definition, 1);
alias_p = node->alias && (!boundary_p || node->weakref); alias_p = node->alias && (!boundary_p || node->weakref);
bp_pack_value (&bp, alias_p, 1); bp_pack_value (&bp, alias_p, 1);
...@@ -1153,6 +1154,7 @@ input_varpool_node (struct lto_file_decl_data *file_data, ...@@ -1153,6 +1154,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
node->forced_by_abi = bp_unpack_value (&bp, 1); node->forced_by_abi = bp_unpack_value (&bp, 1);
node->unique_name = bp_unpack_value (&bp, 1); node->unique_name = bp_unpack_value (&bp, 1);
node->body_removed = 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->definition = bp_unpack_value (&bp, 1);
node->alias = bp_unpack_value (&bp, 1); node->alias = bp_unpack_value (&bp, 1);
node->weakref = 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> 2014-05-16 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/51640 PR c++/51640
......
...@@ -92,7 +92,7 @@ sigfpe (int signum __attribute__ ((unused))) ...@@ -92,7 +92,7 @@ sigfpe (int signum __attribute__ ((unused)))
eliminate the assignment to the global k. */ eliminate the assignment to the global k. */
static int i; static int i;
static int j; static int j;
int k; int k __attribute__ ((used));
int int
main () main ()
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
proper structure. These should be lettered G for the struct that gives 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. */ the name to the .comm, and should be V or S for .lcomm symbols. */
__attribute__ ((used))
static char i_outer; static char i_outer;
struct { struct {
char f1; char f1;
...@@ -15,7 +16,7 @@ struct { ...@@ -15,7 +16,7 @@ struct {
int int
main() main()
{ {
static char i_inner[2]; static char i_inner[2] __attribute__ ((used));
i_inner[0] = 'a'; i_inner[1] = 'b'; i_inner[0] = 'a'; i_inner[1] = 'b';
opta.f1 = 'c'; opta.f1 = 'c';
opta.f2 = 'd'; opta.f2 = 'd';
......
...@@ -7,7 +7,7 @@ foo (long a) ...@@ -7,7 +7,7 @@ foo (long a)
return a + 5; return a + 5;
} }
static long g; static long g __attribute__ ((used));
long __attribute__((noinline, noclone)) long __attribute__((noinline, noclone))
bar (long a) bar (long a)
......
...@@ -9,6 +9,7 @@ void foo (void) ...@@ -9,6 +9,7 @@ void foo (void)
{ {
int toread; int toread;
int bytes; int bytes;
__attribute__ ((used))
static char eof_reached = 0; static char eof_reached = 0;
toread = blocksize; toread = blocksize;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
int foo11 (int c) int foo11 (int c)
{ {
__attribute__ ((used))
static int local1, local2; static int local1, local2;
local1 = 0; local1 = 0;
local2 += c; local2 += c;
......
/* { 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" } } */
...@@ -10,6 +10,7 @@ typedef struct ...@@ -10,6 +10,7 @@ typedef struct
int set_names (void) int set_names (void)
{ {
__attribute__ ((used))
static tx_typ tt1; static tx_typ tt1;
int ln; int ln;
for (ln = 0; ln < 8; ln++) for (ln = 0; ln < 8; ln++)
......
...@@ -8431,7 +8431,7 @@ execute_fixup_cfg (void) ...@@ -8431,7 +8431,7 @@ execute_fixup_cfg (void)
FOR_EACH_BB_FN (bb, cfun) FOR_EACH_BB_FN (bb, cfun)
{ {
bb->count = apply_scale (bb->count, count_scale); 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); gimple stmt = gsi_stmt (gsi);
tree decl = is_gimple_call (stmt) tree decl = is_gimple_call (stmt)
...@@ -8457,9 +8457,46 @@ execute_fixup_cfg (void) ...@@ -8457,9 +8457,46 @@ execute_fixup_cfg (void)
todo |= TODO_cleanup_cfg; 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) if (maybe_clean_eh_stmt (stmt)
&& gimple_purge_dead_eh_edges (bb)) && gimple_purge_dead_eh_edges (bb))
todo |= TODO_cleanup_cfg; todo |= TODO_cleanup_cfg;
gsi_next (&gsi);
} }
FOR_EACH_EDGE (e, ei, bb->succs) FOR_EACH_EDGE (e, ei, bb->succs)
......
...@@ -211,6 +211,8 @@ dump_varpool_node (FILE *f, varpool_node *node) ...@@ -211,6 +211,8 @@ dump_varpool_node (FILE *f, varpool_node *node)
fprintf (f, " read-only"); fprintf (f, " read-only");
if (ctor_for_folding (node->decl) != error_mark_node) if (ctor_for_folding (node->decl) != error_mark_node)
fprintf (f, " const-value-known"); fprintf (f, " const-value-known");
if (node->writeonly)
fprintf (f, " write-only");
fprintf (f, "\n"); fprintf (f, "\n");
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment