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
This commit is contained in:
Jan Hubicka 2014-05-16 19:49:06 +02:00 committed by Jan Hubicka
parent 54674a35bd
commit 6de88c6a1c
14 changed files with 186 additions and 27 deletions

View file

@ -1,3 +1,10 @@
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

View file

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

114
gcc/ipa.c
View file

@ -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)

View file

@ -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);

View file

@ -1,3 +1,20 @@
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

View file

@ -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 ()

View file

@ -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';

View file

@ -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)

View file

@ -9,6 +9,7 @@ void foo (void)
{
int toread;
int bytes;
__attribute__ ((used))
static char eof_reached = 0;
toread = blocksize;

View file

@ -3,6 +3,7 @@
int foo11 (int c)
{
__attribute__ ((used))
static int local1, local2;
local1 = 0;
local2 += c;

View file

@ -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" } } */

View file

@ -10,6 +10,7 @@ typedef struct
int set_names (void)
{
__attribute__ ((used))
static tx_typ tt1;
int ln;
for (ln = 0; ln < 8; ln++)

View file

@ -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)

View file

@ -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");
}