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:
parent
54674a35bd
commit
6de88c6a1c
14 changed files with 186 additions and 27 deletions
|
@ -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
|
||||
|
|
|
@ -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
114
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ()
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -9,6 +9,7 @@ void foo (void)
|
|||
{
|
||||
int toread;
|
||||
int bytes;
|
||||
__attribute__ ((used))
|
||||
static char eof_reached = 0;
|
||||
|
||||
toread = blocksize;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
int foo11 (int c)
|
||||
{
|
||||
__attribute__ ((used))
|
||||
static int local1, local2;
|
||||
local1 = 0;
|
||||
local2 += c;
|
||||
|
|
20
gcc/testsuite/gcc.dg/tree-ssa/writeonly.c
Normal file
20
gcc/testsuite/gcc.dg/tree-ssa/writeonly.c
Normal 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" } } */
|
|
@ -10,6 +10,7 @@ typedef struct
|
|||
|
||||
int set_names (void)
|
||||
{
|
||||
__attribute__ ((used))
|
||||
static tx_typ tt1;
|
||||
int ln;
|
||||
for (ln = 0; ln < 8; ln++)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue