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