2016-02-24 Richard Biener <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 24 Feb 2016 14:54:01 +0000 (14:54 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 24 Feb 2016 14:54:01 +0000 (14:54 +0000)
Jakub Jelinek  <jakub@redhat.com>

PR middle-end/69760
* tree-scalar-evolution.c (interpret_rhs_expr): Re-write
conditionally executed ops to well-defined overflow behavior.

* gcc.dg/torture/pr69760.c: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233669 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr69760.c [new file with mode: 0644]
gcc/tree-scalar-evolution.c

index 53376ae..0c2c960 100644 (file)
@@ -1,3 +1,10 @@
+2016-02-24  Richard Biener  <rguenther@suse.de>
+       Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/69760
+       * tree-scalar-evolution.c (interpret_rhs_expr): Re-write
+       conditionally executed ops to well-defined overflow behavior.
+
 2016-02-24  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/69915
index d956d00..2e41588 100644 (file)
@@ -1,3 +1,9 @@
+2016-02-24  Richard Biener  <rguenther@suse.de>
+       Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/69760
+       * gcc.dg/torture/pr69760.c: New testcase.
+
 2016-02-24  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * gcc.dg/debug/dwarf2/prod-options.c: Use different DW_AT_producer
diff --git a/gcc/testsuite/gcc.dg/torture/pr69760.c b/gcc/testsuite/gcc.dg/torture/pr69760.c
new file mode 100644 (file)
index 0000000..8f24608
--- /dev/null
@@ -0,0 +1,50 @@
+/* PR tree-optimization/69760 */
+/* { dg-do run { target { { *-*-linux* *-*-gnu* } && mmap } } } */
+/* { dg-options "-O2" } */
+
+#include <unistd.h>
+#include <sys/mman.h>
+
+__attribute__((noinline, noclone)) void
+test_func (double *a, int L, int m, int n, int N)
+{
+  int i, k;
+  for (i = 0; i < N; i++)
+    {
+      k = i - m;
+      if (k >= 0 && k < n)
+       a[L * k] = 0.0;
+    }
+}
+
+int
+main ()
+{
+  char *p;
+  int L, m, n, N;
+  long l;
+  L = 10000000;
+  n = 4;
+  N = 100 * n;
+  long pgsz = sysconf(_SC_PAGESIZE);
+  if (pgsz < sizeof (double) || pgsz > L * sizeof (double))
+    return 0;
+  p = mmap ((void *) 0, L * n * sizeof (double), PROT_NONE,
+           MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  if (p == MAP_FAILED)
+    return 0;
+  if (mprotect (p, pgsz, PROT_READ | PROT_WRITE))
+    return 0;
+  l = (L * sizeof (double)) / pgsz * pgsz;
+  if (mprotect (p + l, pgsz, PROT_READ | PROT_WRITE))
+    return 0;
+  l = (2 * L * sizeof (double)) / pgsz * pgsz;
+  if (mprotect (p + l, pgsz, PROT_READ | PROT_WRITE))
+    return 0;
+  l = (3 * L * sizeof (double)) / pgsz * pgsz;
+  if (mprotect (p + l, pgsz, PROT_READ | PROT_WRITE))
+    return 0;
+  for (m = 0; m < N; m += n)
+    test_func ((double *) p, L, m, n, N);
+  return 0;
+}
index c36a039..fdd5da0 100644 (file)
@@ -1703,7 +1703,7 @@ static tree
 interpret_rhs_expr (struct loop *loop, gimple *at_stmt,
                    tree type, tree rhs1, enum tree_code code, tree rhs2)
 {
-  tree res, chrec1, chrec2;
+  tree res, chrec1, chrec2, ctype;
   gimple *def;
 
   if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS)
@@ -1798,30 +1798,63 @@ interpret_rhs_expr (struct loop *loop, gimple *at_stmt,
     case PLUS_EXPR:
       chrec1 = analyze_scalar_evolution (loop, rhs1);
       chrec2 = analyze_scalar_evolution (loop, rhs2);
-      chrec1 = chrec_convert (type, chrec1, at_stmt);
-      chrec2 = chrec_convert (type, chrec2, at_stmt);
+      ctype = type;
+      /* When the stmt is conditionally executed re-write the CHREC
+         into a form that has well-defined behavior on overflow.  */
+      if (at_stmt
+         && INTEGRAL_TYPE_P (type)
+         && ! TYPE_OVERFLOW_WRAPS (type)
+         && ! dominated_by_p (CDI_DOMINATORS, loop->latch,
+                              gimple_bb (at_stmt)))
+       ctype = unsigned_type_for (type);
+      chrec1 = chrec_convert (ctype, chrec1, at_stmt);
+      chrec2 = chrec_convert (ctype, chrec2, at_stmt);
       chrec1 = instantiate_parameters (loop, chrec1);
       chrec2 = instantiate_parameters (loop, chrec2);
-      res = chrec_fold_plus (type, chrec1, chrec2);
+      res = chrec_fold_plus (ctype, chrec1, chrec2);
+      if (type != ctype)
+       res = chrec_convert (type, res, at_stmt);
       break;
 
     case MINUS_EXPR:
       chrec1 = analyze_scalar_evolution (loop, rhs1);
       chrec2 = analyze_scalar_evolution (loop, rhs2);
-      chrec1 = chrec_convert (type, chrec1, at_stmt);
-      chrec2 = chrec_convert (type, chrec2, at_stmt);
+      ctype = type;
+      /* When the stmt is conditionally executed re-write the CHREC
+         into a form that has well-defined behavior on overflow.  */
+      if (at_stmt
+         && INTEGRAL_TYPE_P (type)
+         && ! TYPE_OVERFLOW_WRAPS (type)
+         && ! dominated_by_p (CDI_DOMINATORS,
+                              loop->latch, gimple_bb (at_stmt)))
+       ctype = unsigned_type_for (type);
+      chrec1 = chrec_convert (ctype, chrec1, at_stmt);
+      chrec2 = chrec_convert (ctype, chrec2, at_stmt);
       chrec1 = instantiate_parameters (loop, chrec1);
       chrec2 = instantiate_parameters (loop, chrec2);
-      res = chrec_fold_minus (type, chrec1, chrec2);
+      res = chrec_fold_minus (ctype, chrec1, chrec2);
+      if (type != ctype)
+       res = chrec_convert (type, res, at_stmt);
       break;
 
     case NEGATE_EXPR:
       chrec1 = analyze_scalar_evolution (loop, rhs1);
-      chrec1 = chrec_convert (type, chrec1, at_stmt);
+      ctype = type;
+      /* When the stmt is conditionally executed re-write the CHREC
+         into a form that has well-defined behavior on overflow.  */
+      if (at_stmt
+         && INTEGRAL_TYPE_P (type)
+         && ! TYPE_OVERFLOW_WRAPS (type)
+         && ! dominated_by_p (CDI_DOMINATORS,
+                              loop->latch, gimple_bb (at_stmt)))
+       ctype = unsigned_type_for (type);
+      chrec1 = chrec_convert (ctype, chrec1, at_stmt);
       /* TYPE may be integer, real or complex, so use fold_convert.  */
       chrec1 = instantiate_parameters (loop, chrec1);
-      res = chrec_fold_multiply (type, chrec1,
-                                fold_convert (type, integer_minus_one_node));
+      res = chrec_fold_multiply (ctype, chrec1,
+                                fold_convert (ctype, integer_minus_one_node));
+      if (type != ctype)
+       res = chrec_convert (type, res, at_stmt);
       break;
 
     case BIT_NOT_EXPR:
@@ -1837,11 +1870,22 @@ interpret_rhs_expr (struct loop *loop, gimple *at_stmt,
     case MULT_EXPR:
       chrec1 = analyze_scalar_evolution (loop, rhs1);
       chrec2 = analyze_scalar_evolution (loop, rhs2);
-      chrec1 = chrec_convert (type, chrec1, at_stmt);
-      chrec2 = chrec_convert (type, chrec2, at_stmt);
+      ctype = type;
+      /* When the stmt is conditionally executed re-write the CHREC
+         into a form that has well-defined behavior on overflow.  */
+      if (at_stmt
+         && INTEGRAL_TYPE_P (type)
+         && ! TYPE_OVERFLOW_WRAPS (type)
+         && ! dominated_by_p (CDI_DOMINATORS,
+                              loop->latch, gimple_bb (at_stmt)))
+       ctype = unsigned_type_for (type);
+      chrec1 = chrec_convert (ctype, chrec1, at_stmt);
+      chrec2 = chrec_convert (ctype, chrec2, at_stmt);
       chrec1 = instantiate_parameters (loop, chrec1);
       chrec2 = instantiate_parameters (loop, chrec2);
-      res = chrec_fold_multiply (type, chrec1, chrec2);
+      res = chrec_fold_multiply (ctype, chrec1, chrec2);
+      if (type != ctype)
+       res = chrec_convert (type, res, at_stmt);
       break;
 
     case LSHIFT_EXPR: