re PR tree-optimization/53265 (Warn when undefined behavior implies smaller iteration...
authorJakub Jelinek <jakub@redhat.com>
Thu, 14 Mar 2013 09:13:36 +0000 (10:13 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 14 Mar 2013 09:13:36 +0000 (10:13 +0100)
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

15 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/cfgloop.h
gcc/common.opt
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/longbranch2.C
gcc/testsuite/gcc.dg/pr53265.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr49518.c
gcc/testsuite/gcc.dg/tree-ssa/cunroll-10.c
gcc/tree-ssa-loop-niter.c
libgcc/ChangeLog
libgcc/unwind-dw2.c
libmudflap/ChangeLog
libmudflap/testsuite/libmudflap.c/fail37-frag.c

index 78b3616..c403ca7 100644 (file)
@@ -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
index 6d9ca1b..54ea04f 100644 (file)
@@ -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 \
index 0b2af72..01cef51 100644 (file)
@@ -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;
index 3c7b415..bdbd3b6 100644 (file)
@@ -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
index 7927c6f..9273d7d 100644 (file)
@@ -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
index 231ceb5..19fab0e 100644 (file)
@@ -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
index de63f69..4a8d5ee 100644 (file)
@@ -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 (file)
index 0000000..c60a736
--- /dev/null
@@ -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);
+}
index 84a10fb..55761fd 100644 (file)
@@ -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 };
index 7893565..f2cd904 100644 (file)
@@ -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]++;
 }
index ba06b0c..bcd4317 100644 (file)
@@ -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
index 61f5cc0..aa10774 100644 (file)
@@ -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
index 101a828..80de5ab 100644 (file)
@@ -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:
index 1872b2e..6e0d65c 100644 (file)
@@ -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.
index 41ce4b9..38dbde5 100644 (file)
@@ -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.*" } */