This fixes a missed optimization regarding to coverage counters. In the past we failed to apply proper may-alias analysis and disregarded those counters as being possibly aliased by pointers by accident. The following patch adds a flag so we can mark VAR_DECLs as to be not considered as aliased by pointers so we can make that an informed decision in this case (even though strictly wrong - the address to those counters escapes into the gcov info struct we build and pass to __gcov_init).
Profiledbootstrapped and tested on x86_64-unknown-linux-gnu, ok for trunk? Do we eventually want sth like this for the branch(es)? Thanks, Richard. 2014-03-21 Richard Biener <rguent...@suse.de> PR tree-optimization/60577 * tree-core.h (struct tree_base): Document nothrow_flag use in VAR_DECL_NONALIASED. * tree.h (VAR_DECL_NONALIASED): New. (may_be_aliased): Adjust. * coverage.c (build_var): Set VAR_DECL_NONALIASED. * gcc.dg/tree-ssa/ssa-lim-11.c: New testcase. Index: gcc/tree-core.h =================================================================== *** gcc/tree-core.h (revision 208693) --- gcc/tree-core.h (working copy) *************** struct GTY(()) tree_base { *** 987,992 **** --- 987,995 ---- SSA_NAME_IN_FREELIST in SSA_NAME + VAR_DECL_NONALIASED in + VAR_DECL + deprecated_flag: TREE_DEPRECATED in Index: gcc/tree.h =================================================================== *** gcc/tree.h (revision 208693) --- gcc/tree.h (working copy) *************** extern void decl_fini_priority_insert (t *** 2441,2446 **** --- 2441,2450 ---- #define DECL_NONLOCAL_FRAME(NODE) \ (VAR_DECL_CHECK (NODE)->base.default_def_flag) + /* In a VAR_DECL, nonzero if this variable is not aliased by any pointer. */ + #define DECL_NONALIASED(NODE) \ + (VAR_DECL_CHECK (NODE)->base.nothrow_flag) + /* This field is used to reference anything in decl.result and is meant only for use by the garbage collector. */ #define DECL_RESULT_FLD(NODE) \ *************** static inline bool *** 4462,4473 **** may_be_aliased (const_tree var) { return (TREE_CODE (var) != CONST_DECL - && !((TREE_STATIC (var) || TREE_PUBLIC (var) || DECL_EXTERNAL (var)) - && TREE_READONLY (var) - && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (var))) && (TREE_PUBLIC (var) || DECL_EXTERNAL (var) ! || TREE_ADDRESSABLE (var))); } /* Return pointer to optimization flags of FNDECL. */ --- 4466,4479 ---- may_be_aliased (const_tree var) { return (TREE_CODE (var) != CONST_DECL && (TREE_PUBLIC (var) || DECL_EXTERNAL (var) ! || TREE_ADDRESSABLE (var)) ! && !((TREE_STATIC (var) || TREE_PUBLIC (var) || DECL_EXTERNAL (var)) ! && ((TREE_READONLY (var) ! && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (var))) ! || (TREE_CODE (var) == VAR_DECL ! && DECL_NONALIASED (var))))); } /* Return pointer to optimization flags of FNDECL. */ Index: gcc/coverage.c =================================================================== *** gcc/coverage.c (revision 208693) --- gcc/coverage.c (working copy) *************** build_var (tree fn_decl, tree type, int *** 721,726 **** --- 721,727 ---- DECL_NAME (var) = get_identifier (buf); TREE_STATIC (var) = 1; TREE_ADDRESSABLE (var) = 1; + DECL_NONALIASED (var) = 1; DECL_ALIGN (var) = TYPE_ALIGN (type); return var; Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-11.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-11.c (revision 0) --- gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-11.c (working copy) *************** *** 0 **** --- 1,25 ---- + /* { dg-do compile } */ + /* { dg-options "-O -fprofile-arcs -fdump-tree-lim1-details" } */ + + struct thread_param + { + long* buf; + long iterations; + long accesses; + } param; + + void access_buf(struct thread_param* p) + { + long i,j; + long iterations = p->iterations; + long accesses = p->accesses; + for (i=0; i<iterations; i++) + { + long* pbuf = p->buf; + for (j=0; j<accesses; j++) + pbuf[j] += 1; + } + } + + /* { dg-final { scan-tree-dump-times "Executing store motion of __gcov0.access_buf\\\[\[01\]\\\] from loop 1" 2 "lim1" } } */ + /* { dg-final { cleanup-tree-dump "lim1" } } */