On Fri, 15 Nov 2013, Richard Biener wrote:

> On Fri, 15 Nov 2013, Jakub Jelinek wrote:
> 
> > On Fri, Nov 15, 2013 at 02:56:51PM +0100, Richard Biener wrote:
> > > Now that there is (finally :() a wrong-code testcase for the
> > > PR54570 issue we can no longer ignore it (bah).  So the following
> > > tries to paper over the fact that object-size sucks and disables
> > > value-numbering of equal addresses the same before that pass
> > > had a chance to finally look at the structure of the addresses.
> > > 
> > > To make this "fix" suck less I moved the object-size pass before
> > > the final FRE pass runs which is after IPA inlining and the
> > > propagation of constants and addresses.  You won't catch
> > > any "improvements" you'd get by memory CSE opportunities that
> > > IPA inlining exposes, but you cannot have everything here.
> > 
> > If it doesn't regress anything in the testsuite, I guess that is ok.
> > 
> > > (IMHO object-size would should run during early optimizations)
> > 
> > It can't, because inlining and some limited cleanup afterwards is essential
> > for it.  Otherwise you'd regress not just for __builtin_object_size (x, 1),
> > which admittedly is problematic since the introduction of MEM_REFs and
> > various other changes, but also for __builtin_object_size (x, 0), which
> > would be much more important.
> > 
> > As discussed earlier, perhaps instead of checking cfun->after_inlining
> > you could just introduce a new flag whether cfun contains any
> > __builtin_object_size (x, {1,3}) calls, initialized by the gimplifier,
> > propagated by the inliner and finally cleared again by objsz pass.
> 
> But you'd need to pessimistically initialize it because if you inline
> into a function with __builtin_object_size you may not previously
> optimize.  You can of course analyze the cgraph to clear it for
> functions that cannot end up being inlined into such function.
> So that's effectively the same as ->after_inlining
> minus losing the optimization that didn't end up with 
> __builtin_object_size after that.
> 
> Not sure if it's worth all the trouble.  Arriving at a better
> design for computing __builtin_object_size would be better ;)
> (not that I have one)
> 
> > Of course, if moving objsz earlier seems to work, it could stay where you
> > put it, but the flag could make it clearer why you want to avoid certain
> > optimizations.
> 
> Well, all object-size testcases are pretty simplistic right now and
> don't trigger the IPA inliner for example.
> 
> > > Bootstrap / regtest pending on x86_64-unknown-linux-gnu.
> > > 
> > > Similar candidate for the 4.8 branch.
> > 
> > Please wait sufficiently long for trunk issues before you backport.
> 
> Of course.

So I had to do some more changes because doing objsz earlier (and
separating it from strlenopt) exposes that the GENERIC folders (ugh)
for strcat mess up points-to info as it folds strcat to
memcpy (SAVE_EXPR <dest + strlen ()>, ...) which adds a new
SSA name for the destination with no alias info associated.

Rather than moving the non-constant builtin foldings to GIMPLE
I chose to make sure to forward the constants in objsz and fold
the stmts there (as PTA is re-run shortly after it).

This then breaks some of the scan-tree-dumps in the strlenopt
testcases because nobody has previously folded the _chk builtins
with -1U size to non-_chk variants, so I have to adjust them
(I didn't want to move the strlenopt pass as well).

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Any objections?

Thanks,
Richard.

2013-11-18  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/59125
        PR tree-optimization/54570
        * tree-ssa-sccvn.c (copy_reference_ops_from_ref): When inlining
        is not complete do not treat component-references with offset zero
        but different fields as equal.
        * tree-object-size.c: Include tree-phinodes.h and ssa-iterators.h.
        (compute_object_sizes): Apply TLC.  Propagate the constant
        results into all uses and fold their stmts.
        * passes.def (pass_all_optimizations): Move pass_object_sizes
        after the first pass_forwprop and before pass_fre.

        * gcc.dg/builtin-object-size-8.c: Un-xfail.
        * gcc.dg/builtin-object-size-14.c: New testcase.
        * gcc.dg/strlenopt-14gf.c: Adjust.
        * gcc.dg/strlenopt-1f.c: Likewise.
        * gcc.dg/strlenopt-4gf.c: Likewise.

Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c.orig   2013-11-18 11:20:36.000000000 +0100
--- gcc/tree-ssa-sccvn.c        2013-11-18 11:29:12.300337512 +0100
*************** copy_reference_ops_from_ref (tree ref, v
*** 760,766 ****
      }
  
    /* For non-calls, store the information that makes up the address.  */
! 
    while (ref)
      {
        vn_reference_op_s temp;
--- 760,766 ----
      }
  
    /* For non-calls, store the information that makes up the address.  */
!   tree orig = ref;
    while (ref)
      {
        vn_reference_op_s temp;
*************** copy_reference_ops_from_ref (tree ref, v
*** 810,816 ****
                        + tree_to_double_int (bit_offset)
                        .rshift (BITS_PER_UNIT == 8
                                   ? 3 : exact_log2 (BITS_PER_UNIT));
!                   if (off.fits_shwi ())
                      temp.off = off.low;
                  }
              }
--- 810,819 ----
                        + tree_to_double_int (bit_offset)
                        .rshift (BITS_PER_UNIT == 8
                                   ? 3 : exact_log2 (BITS_PER_UNIT));
!                   if (off.fits_shwi ()
!                       && (TREE_CODE (orig) != ADDR_EXPR
!                           || !off.is_zero ()
!                           || cfun->after_inlining))
                      temp.off = off.low;
                  }
              }
Index: gcc/passes.def
===================================================================
*** gcc/passes.def.orig 2013-11-18 11:20:36.000000000 +0100
--- gcc/passes.def      2013-11-18 11:29:12.305337567 +0100
*************** along with GCC; see the file COPYING3.
*** 142,147 ****
--- 142,148 ----
         form if possible.  */
        NEXT_PASS (pass_phiprop);
        NEXT_PASS (pass_forwprop);
+       NEXT_PASS (pass_object_sizes);
        /* pass_build_alias is a dummy pass that ensures that we
         execute TODO_rebuild_alias at this point.  */
        NEXT_PASS (pass_build_alias);
*************** along with GCC; see the file COPYING3.
*** 185,191 ****
        NEXT_PASS (pass_dce);
        NEXT_PASS (pass_forwprop);
        NEXT_PASS (pass_phiopt);
-       NEXT_PASS (pass_object_sizes);
        NEXT_PASS (pass_strlen);
        NEXT_PASS (pass_ccp);
        /* After CCP we rewrite no longer addressed locals into SSA
--- 186,191 ----
Index: gcc/testsuite/gcc.dg/builtin-object-size-8.c
===================================================================
*** gcc/testsuite/gcc.dg/builtin-object-size-8.c.orig   2013-11-18 
11:20:36.000000000 +0100
--- gcc/testsuite/gcc.dg/builtin-object-size-8.c        2013-11-18 
11:29:12.305337567 +0100
***************
*** 1,4 ****
! /* { dg-do run { xfail *-*-* } } */
  /* { dg-options "-O2" } */
  
  typedef __SIZE_TYPE__ size_t;
--- 1,4 ----
! /* { dg-do run } */
  /* { dg-options "-O2" } */
  
  typedef __SIZE_TYPE__ size_t;
Index: gcc/testsuite/gcc.dg/builtin-object-size-14.c
===================================================================
*** /dev/null   1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/builtin-object-size-14.c       2013-11-18 
11:29:12.306337579 +0100
***************
*** 0 ****
--- 1,28 ----
+ /* { dg-do run } */
+ /* { dg-options "-O2" } */
+ 
+ extern void abort (void);
+ extern char *strncpy(char *, const char *, __SIZE_TYPE__);
+ 
+ union u {
+     struct {
+       char vi[8];
+       char pi[16];
+     };
+     char all[8+16+4];
+ };
+ 
+ void __attribute__((noinline,noclone))
+ f(union u *u)
+ {
+   char vi[8+1];
+   __builtin_strncpy(vi, u->vi, sizeof(u->vi));
+   if (__builtin_object_size (u->all, 1) != -1)
+     abort ();
+ }
+ int main()
+ {
+   union u u;
+   f (&u);
+   return 0;
+ }
Index: gcc/tree-object-size.c
===================================================================
*** gcc/tree-object-size.c.orig 2013-11-18 11:20:36.000000000 +0100
--- gcc/tree-object-size.c      2013-11-18 11:29:12.306337579 +0100
*************** along with GCC; see the file COPYING3.
*** 32,37 ****
--- 32,39 ----
  #include "tree-ssanames.h"
  #include "tree-pass.h"
  #include "tree-ssa-propagate.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
  
  struct object_size_info
  {
*************** compute_object_sizes (void)
*** 1207,1222 ****
        gimple_stmt_iterator i;
        for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
        {
!         tree callee, result;
          gimple call = gsi_stmt (i);
! 
!           if (gimple_code (call) != GIMPLE_CALL)
!           continue;
! 
!         callee = gimple_call_fndecl (call);
!         if (!callee
!             || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
!             || DECL_FUNCTION_CODE (callee) != BUILT_IN_OBJECT_SIZE)
            continue;
  
          init_object_sizes ();
--- 1209,1217 ----
        gimple_stmt_iterator i;
        for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
        {
!         tree result;
          gimple call = gsi_stmt (i);
!         if (!gimple_call_builtin_p (call, BUILT_IN_OBJECT_SIZE))
            continue;
  
          init_object_sizes ();
*************** compute_object_sizes (void)
*** 1245,1264 ****
                continue;
            }
  
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
              fprintf (dump_file, "Simplified\n  ");
              print_gimple_stmt (dump_file, call, 0, dump_flags);
            }
  
!         if (!update_call_from_tree (&i, result))
!           gcc_unreachable ();
  
!         if (dump_file && (dump_flags & TDF_DETAILS))
            {
!             fprintf (dump_file, "to\n  ");
!             print_gimple_stmt (dump_file, gsi_stmt (i), 0, dump_flags);
!             fprintf (dump_file, "\n");
            }
        }
      }
--- 1240,1271 ----
                continue;
            }
  
+         gcc_assert (TREE_CODE (result) == INTEGER_CST);
+ 
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
              fprintf (dump_file, "Simplified\n  ");
              print_gimple_stmt (dump_file, call, 0, dump_flags);
+             fprintf (dump_file, " to ");
+             print_generic_expr (dump_file, result, 0);
+             fprintf (dump_file, "\n");
            }
  
!         tree lhs = gimple_call_lhs (call);
!         if (!lhs)
!           continue;
  
!         /* Propagate into all uses and fold those stmts.  */
!         gimple use_stmt;
!         imm_use_iterator iter;
!         FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
            {
!             use_operand_p use_p;
!             FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
!               SET_USE (use_p, result);
!             gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
!             if (fold_stmt (&gsi))
!               update_stmt (gsi_stmt (gsi));
            }
        }
      }
Index: gcc/testsuite/gcc.dg/strlenopt-14gf.c
===================================================================
*** gcc/testsuite/gcc.dg/strlenopt-14gf.c.orig  2013-06-11 09:32:56.000000000 
+0200
--- gcc/testsuite/gcc.dg/strlenopt-14gf.c       2013-11-18 11:33:46.303480430 
+0100
***************
*** 11,24 ****
     memcpy.  */
  /* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "__mempcpy_chk \\(" 2 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 3 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "memcpy \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "mempcpy \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
  /* { dg-final { cleanup-tree-dump "strlen" } } */
--- 11,24 ----
     memcpy.  */
  /* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "__mempcpy_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "mempcpy \\(" 2 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "stpcpy \\(" 2 "strlen" } } */
  /* { dg-final { cleanup-tree-dump "strlen" } } */
Index: gcc/testsuite/gcc.dg/strlenopt-1f.c
===================================================================
*** gcc/testsuite/gcc.dg/strlenopt-1f.c.orig    2013-11-15 15:49:12.000000000 
+0100
--- gcc/testsuite/gcc.dg/strlenopt-1f.c 2013-11-18 11:30:53.643500139 +0100
***************
*** 6,17 ****
  #include "strlenopt-1.c"
  
  /* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 4 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "memcpy \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
--- 6,17 ----
  #include "strlenopt-1.c"
  
  /* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
Index: gcc/testsuite/gcc.dg/strlenopt-4gf.c
===================================================================
*** gcc/testsuite/gcc.dg/strlenopt-4gf.c.orig   2013-06-11 09:32:55.000000000 
+0200
--- gcc/testsuite/gcc.dg/strlenopt-4gf.c        2013-11-18 11:31:12.352714788 
+0100
***************
*** 7,19 ****
  #include "strlenopt-4.c"
  
  /* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 4 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 1 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 5 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "memcpy \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
  /* { dg-final { cleanup-tree-dump "strlen" } } */
--- 7,19 ----
  #include "strlenopt-4.c"
  
  /* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */
  /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "stpcpy \\(" 5 "strlen" } } */
  /* { dg-final { cleanup-tree-dump "strlen" } } */

Reply via email to