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

Reply via email to