diff options
author | Jakub Jelinek <jakub@redhat.com> | 2013-03-14 10:13:36 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2013-03-14 10:13:36 +0100 |
commit | fbd28bc3b2c3394db09577ff2f5a594d50c75b2c (patch) | |
tree | 20df72f941802d316ad1e5b63a60b221cc29586a | |
parent | df2dfaea4e76a6159e733073aff5aa5e6837289a (diff) | |
download | gcc-fbd28bc3b2c3394db09577ff2f5a594d50c75b2c.zip gcc-fbd28bc3b2c3394db09577ff2f5a594d50c75b2c.tar.gz gcc-fbd28bc3b2c3394db09577ff2f5a594d50c75b2c.tar.bz2 |
re PR tree-optimization/53265 (Warn when undefined behavior implies smaller iteration count)
PR tree-optimization/53265
* common.opt (Waggressive-loop-optimizations): New option.
* tree-ssa-loop-niter.c: Include tree-pass.h.
(do_warn_aggressive_loop_optimizations): New function.
(record_estimate): Call it. Don't add !is_exit bounds to loop->bounds
if number_of_latch_executions returned constant.
(estimate_numbers_of_iterations_loop): Call number_of_latch_executions
early. If number_of_latch_executions returned constant, set
nb_iterations_upper_bound back to it.
* cfgloop.h (struct loop): Add warned_aggressive_loop_optimizations
field.
* Makefile.in (tree-ssa-loop-niter.o): Depend on $(TREE_PASS_H).
* doc/invoke.texi (-Wno-aggressive-loop-optimizations): Document.
* gcc.dg/pr53265.c: New test.
* gcc.dg/torture/pr49518.c: Add -Wno-aggressive-loop-optimizations
to dg-options.
* g++.dg/opt/longbranch2.C (EBCOTLut): Double sizes of a2 and a3
arrays.
* gcc.dg/tree-ssa/cunroll-10.c (main): Rename to foo. Add argument
n, use it as high bound instead of 4.
* unwind-dw2.c (execute_cfa_program): Avoid
-Waggressive-array-optimizations warnings for DW_CFA_GNU_window_save
on targets with DWARF_FRAME_REGISTERS < 32.
* testsuite/libmudflap.c/fail37-frag.c: Add optimization barrier.
From-SVN: r196650
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/cfgloop.h | 4 | ||||
-rw-r--r-- | gcc/common.opt | 4 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/longbranch2.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr53265.c | 156 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr49518.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/cunroll-10.c | 5 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 61 | ||||
-rw-r--r-- | libgcc/ChangeLog | 7 | ||||
-rw-r--r-- | libgcc/unwind-dw2.c | 11 | ||||
-rw-r--r-- | libmudflap/ChangeLog | 5 | ||||
-rw-r--r-- | libmudflap/testsuite/libmudflap.c/fail37-frag.c | 6 |
15 files changed, 286 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 78b3616..c403ca7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,19 @@ 2013-03-14 Jakub Jelinek <jakub@redhat.com> + PR tree-optimization/53265 + * common.opt (Waggressive-loop-optimizations): New option. + * tree-ssa-loop-niter.c: Include tree-pass.h. + (do_warn_aggressive_loop_optimizations): New function. + (record_estimate): Call it. Don't add !is_exit bounds to loop->bounds + if number_of_latch_executions returned constant. + (estimate_numbers_of_iterations_loop): Call number_of_latch_executions + early. If number_of_latch_executions returned constant, set + nb_iterations_upper_bound back to it. + * cfgloop.h (struct loop): Add warned_aggressive_loop_optimizations + field. + * Makefile.in (tree-ssa-loop-niter.o): Depend on $(TREE_PASS_H). + * doc/invoke.texi (-Wno-aggressive-loop-optimizations): Document. + * config/aarch64/t-aarch64-linux (MULTARCH_DIRNAME): Remove. (MULTILIB_OSDIRNAMES): Set. * genmultilib: If defaultosdirname doesn't start with :: , set diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 6d9ca1b..54ea04f 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2446,7 +2446,7 @@ tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_FLOW_H) $(CONFIG_H) \ $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \ $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h dumpfile.h \ $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(TREE_DATA_REF_H) \ - $(BASIC_BLOCK_H) $(GGC_H) intl.h $(GIMPLE_PRETTY_PRINT_H) + $(BASIC_BLOCK_H) $(GGC_H) intl.h $(GIMPLE_PRETTY_PRINT_H) $(TREE_PASS_H) tree-ssa-loop-ivcanon.o : tree-ssa-loop-ivcanon.c $(TREE_FLOW_H) $(CONFIG_H) \ $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \ $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h \ diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index 0b2af72..01cef51 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -159,6 +159,10 @@ struct GTY ((chain_next ("%h.next"))) loop { /* True if the loop can be parallel. */ bool can_be_parallel; + /* True if -Waggressive-loop-optimizations warned about this loop + already. */ + bool warned_aggressive_loop_optimizations; + /* An integer estimation of the number of iterations. Estimate_state describes what is the state of the estimation. */ enum loop_estimation estimate_state; diff --git a/gcc/common.opt b/gcc/common.opt index 3c7b415..bdbd3b6c 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -505,6 +505,10 @@ Waggregate-return Common Var(warn_aggregate_return) Warning Warn about returning structures, unions or arrays +Waggressive-loop-optimizations +Common Var(warn_aggressive_loop_optimizations) Init(1) Warning +Warn if a loop with constant number of iterations triggers undefined behavior + Warray-bounds Common Var(warn_array_bounds) Warning Warn if an array is accessed out of bounds diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7927c6f..9273d7d 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -232,7 +232,8 @@ Objective-C and Objective-C++ Dialects}. @xref{Warning Options,,Options to Request or Suppress Warnings}. @gccoptlist{-fsyntax-only -fmax-errors=@var{n} -Wpedantic @gol -pedantic-errors @gol --w -Wextra -Wall -Waddress -Waggregate-return -Warray-bounds @gol +-w -Wextra -Wall -Waddress -Waggregate-return @gol +-Waggressive-loop-optimizations -Warray-bounds @gol -Wno-attributes -Wno-builtin-macro-redefined @gol -Wc++-compat -Wc++11-compat -Wcast-align -Wcast-qual @gol -Wchar-subscripts -Wclobbered -Wcomment @gol @@ -4423,6 +4424,12 @@ Warn if any functions that return structures or unions are defined or called. (In languages where you can return an array, this also elicits a warning.) +@item -Wno-aggressive-loop-optimizations +@opindex Wno-aggressive-loop-optimizations +@opindex Waggressive-loop-optimizations +Warn if in a loop with constant number of iterations the compiler detects +undefined behavior in some statement during one or more of the iterations. + @item -Wno-attributes @opindex Wno-attributes @opindex Wattributes diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 231ceb5..19fab0e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2013-03-14 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/53265 + * gcc.dg/pr53265.c: New test. + * gcc.dg/torture/pr49518.c: Add -Wno-aggressive-loop-optimizations + to dg-options. + * g++.dg/opt/longbranch2.C (EBCOTLut): Double sizes of a2 and a3 + arrays. + * gcc.dg/tree-ssa/cunroll-10.c (main): Rename to foo. Add argument + n, use it as high bound instead of 4. + 2013-03-13 Oleg Endo <olegendo@gcc.gnu.org> PR target/49880 diff --git a/gcc/testsuite/g++.dg/opt/longbranch2.C b/gcc/testsuite/g++.dg/opt/longbranch2.C index de63f69..4a8d5ee 100644 --- a/gcc/testsuite/g++.dg/opt/longbranch2.C +++ b/gcc/testsuite/g++.dg/opt/longbranch2.C @@ -15,8 +15,8 @@ public: class EBCOTLut : public JKeeper { unsigned char a1[1<<8]; - unsigned char a2[1<<8]; - unsigned char a3[1<<8]; + unsigned char a2[1<<9]; + unsigned char a3[1<<9]; long a4[1<<9]; public: EBCOTLut(void); diff --git a/gcc/testsuite/gcc.dg/pr53265.c b/gcc/testsuite/gcc.dg/pr53265.c new file mode 100644 index 0000000..c60a736 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr53265.c @@ -0,0 +1,156 @@ +/* PR tree-optimization/53265 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wall" } */ + +void bar (void *); +int baz (int); + +void +fn1 (void) +{ + unsigned int a[128]; + int i; + + for (i = 0; i < 128; ++i) /* { dg-message "note: containing loop" } */ + a[i] = i * 0x02000001; /* { dg-warning "invokes undefined behavior" } */ + bar (a); +} + +void +fn2 (void) +{ + unsigned long long a[128]; + int i; + + for (i = 0; i < 128; i++) /* { dg-message "note: containing loop" } */ + a[i] = (i + 1LL) * 0x0123456789ABCDEFLL; /* { dg-warning "invokes undefined behavior" } */ + bar (a); +} + +void +fn3 (void) +{ + unsigned char a[16], b[16], c[16]; + int i; + + bar (b); + for (i = 0; i < (int) (sizeof (a) / sizeof (a[0])); i++) /* { dg-message "note: containing loop" } */ + { + c[i + 8] = b[i]; /* { dg-warning "invokes undefined behavior" } */ + a[i + 8] = b[i + 8]; + } + bar (a); + bar (c); +} + +void +fn4 (void) +{ + unsigned int *a[32], *o, i; + + bar (a); + for (i = 0; i <= sizeof (a) / sizeof (a[0]); i++) /* { dg-message "note: containing loop" "" { xfail *-*-* } } */ + { + o = a[i]; /* { dg-warning "invokes undefined behavior" "" { xfail *-*-* } } */ + bar (o); + } +} + +void +fn5 (void) +{ + unsigned short a[23940]; + unsigned int b[1140]; + int j; + + bar (b); + for (j = 0; j < 1140; j++) /* { dg-message "note: containing loop" } */ + a[23940 + j - 950] = b[j]; /* { dg-warning "invokes undefined behavior" } */ + bar (a); +} + +void +fn6 (void) +{ + double a[4][3], b[12]; + int i; + bar (b); + for (i = 0; i < 12; i++) /* { dg-message "note: containing loop" } */ + a[0][i] = b[i] / 10000.0; /* { dg-warning "invokes undefined behavior" } */ + bar (a); +} + +void +fn7 (void) +{ + int a[16], b, c; + bar (a); + for (b = a[c = 0]; c < 16; b = a[++c]) /* { dg-warning "invokes undefined behavior" "" { xfail *-*-* } } */ + baz (b); +} + +/* { dg-message "note: containing loop" "" { xfail *-*-* } 88 } */ + +const void *va, *vb, *vc, *vd, *ve; +const void *vf[4]; +void +fn8 (void) +{ + unsigned long i; + vf[0] = va; vf[1] = vb; vf[2] = vc; vf[3] = vd; + for (i = 0; i < (sizeof (vf) / sizeof (vf[0])); i++) + if (!vf[i]) + vf[i] = ve; +} + +int wa, wb[53][5], wc[53][5]; + +void +fn9 (void) +{ + int i, j, k; + for (i = 0; i < 53; i++) + for (j = 16 / (((wa & 1) != 0) ? 8 : 4); j > 0; j--) + { + int d = 1; + if (wb[i][j] == 0 || wc[i][1] != 0) + continue; + for (k = 0; k < j; k++) + if (wc[i + k][1]) + { + d = 0; + break; + } + if (!d) + continue; + wc[i][j] = baz (0); + } +} + +int xa[18]; + +void +fn10 (void) +{ + int i; + for (i = 16; i < 32; i++) /* { dg-message "note: containing loop" } */ + xa[i] = 26; /* { dg-warning "invokes undefined behavior" } */ +} + +__attribute__((noinline)) static void +fn11 (int x) +{ + int i = 1; + if (x > 1) + do + baz (i); + while (++i != x); /* { dg-bogus "invokes undefined behavior" } */ +} + +void +fn12 (void) +{ + fn11 (1); + fn11 (1); + fn11 (1); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr49518.c b/gcc/testsuite/gcc.dg/torture/pr49518.c index 84a10fb..55761fd 100644 --- a/gcc/testsuite/gcc.dg/torture/pr49518.c +++ b/gcc/testsuite/gcc.dg/torture/pr49518.c @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-options "-Wno-aggressive-loop-optimizations" } */ int a, b; struct S { unsigned int s, t, u; } c, d = { 0, 1, 0 }; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-10.c b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-10.c index 7893565..f2cd904 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-10.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-10.c @@ -2,10 +2,11 @@ /* { dg-options "-O3 -Warray-bounds -fdump-tree-cunroll-details" } */ int a[3]; int b[4]; -main() +int +foo (int n) { int i; - for (i=0;i<4;i++) + for (i=0;i<n;i++) if (b[i]==2) a[i]++; } diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index ba06b0c..bcd4317 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "diagnostic-core.h" #include "tree-inline.h" +#include "tree-pass.h" #define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while (0) @@ -2525,6 +2526,40 @@ record_niter_bound (struct loop *loop, double_int i_bound, bool realistic, loop->nb_iterations_estimate = loop->nb_iterations_upper_bound; } +/* Emit a -Waggressive-loop-optimizations warning if needed. */ + +static void +do_warn_aggressive_loop_optimizations (struct loop *loop, + double_int i_bound, gimple stmt) +{ + /* Don't warn if the loop doesn't have known constant bound. */ + if (!loop->nb_iterations + || TREE_CODE (loop->nb_iterations) != INTEGER_CST + || !warn_aggressive_loop_optimizations + /* To avoid warning multiple times for the same loop, + only start warning when we preserve loops. */ + || (cfun->curr_properties & PROP_loops) == 0 + /* Only warn once per loop. */ + || loop->warned_aggressive_loop_optimizations + /* Only warn if undefined behavior gives us lower estimate than the + known constant bound. */ + || i_bound.ucmp (tree_to_double_int (loop->nb_iterations)) >= 0 + /* And undefined behavior happens unconditionally. */ + || !dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (stmt))) + return; + + edge e = single_exit (loop); + if (e == NULL) + return; + + gimple estmt = last_stmt (e->src); + warning_at (gimple_location (stmt), OPT_Waggressive_loop_optimizations, + "iteration %E invokes undefined behavior", + double_int_to_tree (TREE_TYPE (loop->nb_iterations), i_bound)); + inform (gimple_location (estmt), "containing loop"); + loop->warned_aggressive_loop_optimizations = true; +} + /* Records that AT_STMT is executed at most BOUND + 1 times in LOOP. IS_EXIT is true if the loop is exited immediately after STMT, and this exit is taken at last when the STMT is executed BOUND + 1 times. @@ -2560,8 +2595,12 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound, return; /* If we have a guaranteed upper bound, record it in the appropriate - list. */ - if (upper) + list, unless this is an !is_exit bound (i.e. undefined behavior in + at_stmt) in a loop with known constant number of iterations. */ + if (upper + && (is_exit + || loop->nb_iterations == NULL_TREE + || TREE_CODE (loop->nb_iterations) != INTEGER_CST)) { struct nb_iter_bound *elt = ggc_alloc_nb_iter_bound (); @@ -2591,6 +2630,8 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound, if (i_bound.ult (delta)) return; + if (upper && !is_exit) + do_warn_aggressive_loop_optimizations (loop, i_bound, at_stmt); record_niter_bound (loop, i_bound, realistic, upper); } @@ -3311,6 +3352,11 @@ estimate_numbers_of_iterations_loop (struct loop *loop) /* Force estimate compuation but leave any existing upper bound in place. */ loop->any_estimate = false; + /* Ensure that loop->nb_iterations is computed if possible. If it turns out + to be constant, we avoid undefined behavior implied bounds and instead + diagnose those loops with -Waggressive-loop-optimizations. */ + number_of_latch_executions (loop); + exits = get_loop_exit_edges (loop); likely_exit = single_likely_exit (loop); FOR_EACH_VEC_ELT (exits, i, ex) @@ -3345,6 +3391,17 @@ estimate_numbers_of_iterations_loop (struct loop *loop) bound = gcov_type_to_double_int (nit); record_niter_bound (loop, bound, true, false); } + + /* If we know the exact number of iterations of this loop, try to + not break code with undefined behavior by not recording smaller + maximum number of iterations. */ + if (loop->nb_iterations + && TREE_CODE (loop->nb_iterations) == INTEGER_CST) + { + loop->any_upper_bound = true; + loop->nb_iterations_upper_bound + = tree_to_double_int (loop->nb_iterations); + } } /* Sets NIT to the estimated number of executions of the latch of the diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 61f5cc07..aa10774 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,10 @@ +2013-03-14 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/53265 + * unwind-dw2.c (execute_cfa_program): Avoid + -Waggressive-array-optimizations warnings for DW_CFA_GNU_window_save + on targets with DWARF_FRAME_REGISTERS < 32. + 2013-03-13 Oleg Endo <olegendo@gcc.gnu.org> PR target/49880 diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c index 101a828..80de5ab 100644 --- a/libgcc/unwind-dw2.c +++ b/libgcc/unwind-dw2.c @@ -1128,11 +1128,12 @@ execute_cfa_program (const unsigned char *insn_ptr, case DW_CFA_GNU_window_save: /* ??? Hardcoded for SPARC register window configuration. */ - for (reg = 16; reg < 32; ++reg) - { - fs->regs.reg[reg].how = REG_SAVED_OFFSET; - fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *); - } + if (DWARF_FRAME_REGISTERS >= 32) + for (reg = 16; reg < 32; ++reg) + { + fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *); + } break; case DW_CFA_GNU_args_size: diff --git a/libmudflap/ChangeLog b/libmudflap/ChangeLog index 1872b2e..6e0d65c 100644 --- a/libmudflap/ChangeLog +++ b/libmudflap/ChangeLog @@ -1,3 +1,8 @@ +2013-03-14 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/53265 + * testsuite/libmudflap.c/fail37-frag.c: Add optimization barrier. + 2013-02-03 Richard Sandiford <rdsandiford@googlemail.com> Update copyright years. diff --git a/libmudflap/testsuite/libmudflap.c/fail37-frag.c b/libmudflap/testsuite/libmudflap.c/fail37-frag.c index 41ce4b9..38dbde5 100644 --- a/libmudflap/testsuite/libmudflap.c/fail37-frag.c +++ b/libmudflap/testsuite/libmudflap.c/fail37-frag.c @@ -13,7 +13,11 @@ main () { int i; for (i = 0; i < 5; i++) - x.s[i].f = 0; + { + /* Optimization barrier. Prevent gcc from seeing the undefined behavior. */ + __asm ("" : "+r" (i)); + x.s[i].f = 0; + } exit (0); } /* { dg-output "mudflap violation 1.*" } */ |