re PR tree-optimization/81661 (ICE in gimplify_modify_expr, at gimplify.c:5638)
authorJakub Jelinek <jakub@redhat.com>
Thu, 1 Feb 2018 10:08:26 +0000 (11:08 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 1 Feb 2018 10:08:26 +0000 (11:08 +0100)
PR tree-optimization/81661
PR tree-optimization/84117
* tree-eh.h (rewrite_to_non_trapping_overflow): Declare.
* tree-eh.c: Include gimplify.h.
(find_trapping_overflow, replace_trapping_overflow,
rewrite_to_non_trapping_overflow): New functions.
* tree-vect-loop.c: Include tree-eh.h.
(vect_get_loop_niters): Use rewrite_to_non_trapping_overflow.
* tree-data-ref.c: Include tree-eh.h.
(get_segment_min_max): Use rewrite_to_non_trapping_overflow.

* gcc.dg/pr81661.c: New test.
* gfortran.dg/pr84117.f90: New test.

From-SVN: r257284

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr81661.c [new file with mode: 0644]
gcc/testsuite/gfortran.dg/pr84117.f90 [new file with mode: 0644]
gcc/tree-data-ref.c
gcc/tree-eh.c
gcc/tree-eh.h
gcc/tree-vect-loop.c

index 88df7ab..b1c5617 100644 (file)
@@ -1,3 +1,16 @@
+2018-02-01  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/81661
+       PR tree-optimization/84117
+       * tree-eh.h (rewrite_to_non_trapping_overflow): Declare.
+       * tree-eh.c: Include gimplify.h.
+       (find_trapping_overflow, replace_trapping_overflow,
+       rewrite_to_non_trapping_overflow): New functions.
+       * tree-vect-loop.c: Include tree-eh.h.
+       (vect_get_loop_niters): Use rewrite_to_non_trapping_overflow.
+       * tree-data-ref.c: Include tree-eh.h.
+       (get_segment_min_max): Use rewrite_to_non_trapping_overflow.
+
 2018-01-31  Uros Bizjak  <ubizjak@gmail.com>
 
        PR rtl-optimization/84123
index 778ba75..92d013e 100644 (file)
@@ -1,3 +1,10 @@
+2018-02-01  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/81661
+       PR tree-optimization/84117
+       * gcc.dg/pr81661.c: New test.
+       * gfortran.dg/pr84117.f90: New test.
+
 2018-02-01  Janne Blomqvist  <jb@gcc.gnu.org>
 
        PR fortran/83705
diff --git a/gcc/testsuite/gcc.dg/pr81661.c b/gcc/testsuite/gcc.dg/pr81661.c
new file mode 100644 (file)
index 0000000..d8d2730
--- /dev/null
@@ -0,0 +1,12 @@
+/* PR tree-optimization/81661 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -ftrapv" } */
+
+int a, b, c;
+
+void
+foo (void)
+{
+  while (a + c > b)
+    a--;
+}
diff --git a/gcc/testsuite/gfortran.dg/pr84117.f90 b/gcc/testsuite/gfortran.dg/pr84117.f90
new file mode 100644 (file)
index 0000000..1853d8c
--- /dev/null
@@ -0,0 +1,7 @@
+! PR tree-optimization/84117
+! { dg-do compile }
+! { dg-options "-O3 -ftrapv" }
+  FUNCTION pw_integral_aa ( cc ) RESULT ( integral_value )
+    COMPLEX(KIND=8), DIMENSION(:), POINTER :: cc
+    integral_value = accurate_sum ( CONJG ( cc (:) ) * cc (:) )
+  END FUNCTION pw_integral_aa
index 0b6ad5f..b5c0b7f 100644 (file)
@@ -98,6 +98,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "tree-vrp.h"
 #include "tree-ssanames.h"
+#include "tree-eh.h"
 
 static struct datadep_stats
 {
@@ -1790,7 +1791,8 @@ get_segment_min_max (const dr_with_seg_len &d, tree *seg_min_out,
   tree addr_base = fold_build_pointer_plus (DR_BASE_ADDRESS (d.dr),
                                            DR_OFFSET (d.dr));
   addr_base = fold_build_pointer_plus (addr_base, DR_INIT (d.dr));
-  tree seg_len = fold_convert (sizetype, d.seg_len);
+  tree seg_len
+    = fold_convert (sizetype, rewrite_to_non_trapping_overflow (d.seg_len));
 
   tree min_reach = fold_build3 (COND_EXPR, sizetype, neg_step,
                                seg_len, size_zero_node);
index 3f54623..75385f7 100644 (file)
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "attribs.h"
 #include "asan.h"
+#include "gimplify.h"
 
 /* In some instances a tree and a gimple need to be stored in a same table,
    i.e. in hash tables. This is a structure to do this. */
@@ -2720,6 +2721,91 @@ tree_could_trap_p (tree expr)
     }
 }
 
+/* Return non-NULL if there is an integer operation with trapping overflow
+   we can rewrite into non-trapping.  Called via walk_tree from
+   rewrite_to_non_trapping_overflow.  */
+
+static tree
+find_trapping_overflow (tree *tp, int *walk_subtrees, void *data)
+{
+  if (EXPR_P (*tp)
+      && !operation_no_trapping_overflow (TREE_TYPE (*tp), TREE_CODE (*tp)))
+    return *tp;
+  if (IS_TYPE_OR_DECL_P (*tp)
+      || (TREE_CODE (*tp) == SAVE_EXPR && data == NULL))
+    *walk_subtrees = 0;
+  return NULL_TREE;
+}
+
+/* Rewrite selected operations into unsigned arithmetics, so that they
+   don't trap on overflow.  */
+
+static tree
+replace_trapping_overflow (tree *tp, int *walk_subtrees, void *data)
+{
+  if (find_trapping_overflow (tp, walk_subtrees, data))
+    {
+      tree type = TREE_TYPE (*tp);
+      tree utype = unsigned_type_for (type);
+      *walk_subtrees = 0;
+      int len = TREE_OPERAND_LENGTH (*tp);
+      for (int i = 0; i < len; ++i)
+       walk_tree (&TREE_OPERAND (*tp, i), replace_trapping_overflow,
+                  data, (hash_set<tree> *) data);
+
+      if (TREE_CODE (*tp) == ABS_EXPR)
+       {
+         tree op = TREE_OPERAND (*tp, 0);
+         op = save_expr (op);
+         /* save_expr skips simple arithmetics, which is undesirable
+            here, if it might trap due to flag_trapv.  We need to
+            force a SAVE_EXPR in the COND_EXPR condition, to evaluate
+            it before the comparison.  */
+         if (EXPR_P (op)
+             && TREE_CODE (op) != SAVE_EXPR
+             && walk_tree (&op, find_trapping_overflow, NULL, NULL))
+           {
+             op = build1_loc (EXPR_LOCATION (op), SAVE_EXPR, type, op);
+             TREE_SIDE_EFFECTS (op) = 1;
+           }
+         /* Change abs (op) to op < 0 ? -op : op and handle the NEGATE_EXPR
+            like other signed integer trapping operations.  */
+         tree cond = fold_build2 (LT_EXPR, boolean_type_node,
+                                  op, build_int_cst (type, 0));
+         tree neg = fold_build1 (NEGATE_EXPR, utype,
+                                 fold_convert (utype, op));
+         *tp = fold_build3 (COND_EXPR, type, cond,
+                            fold_convert (type, neg), op);
+       }
+      else
+       {
+         TREE_TYPE (*tp) = utype;
+         len = TREE_OPERAND_LENGTH (*tp);
+         for (int i = 0; i < len; ++i)
+           TREE_OPERAND (*tp, i)
+             = fold_convert (utype, TREE_OPERAND (*tp, i));
+         *tp = fold_convert (type, *tp);
+       }
+    }
+  return NULL_TREE;
+}
+
+/* If any subexpression of EXPR can trap due to -ftrapv, rewrite it
+   using unsigned arithmetics to avoid traps in it.  */
+
+tree
+rewrite_to_non_trapping_overflow (tree expr)
+{
+  if (!flag_trapv)
+    return expr;
+  hash_set<tree> pset;
+  if (!walk_tree (&expr, find_trapping_overflow, &pset, &pset))
+    return expr;
+  expr = unshare_expr (expr);
+  pset.empty ();
+  walk_tree (&expr, replace_trapping_overflow, &pset, &pset);
+  return expr;
+}
 
 /* Helper for stmt_could_throw_p.  Return true if STMT (assumed to be a
    an assignment or a conditional) may throw.  */
index 6e1fa71..11e096c 100644 (file)
@@ -37,6 +37,7 @@ extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool,
                                           bool, tree, bool *);
 extern bool operation_could_trap_p (enum tree_code, bool, bool, tree);
 extern bool tree_could_trap_p (tree);
+extern tree rewrite_to_non_trapping_overflow (tree);
 extern bool stmt_could_throw_p (gimple *);
 extern bool tree_could_throw_p (tree);
 extern bool stmt_can_throw_external (gimple *);
index f75a483..c530168 100644 (file)
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "internal-fn.h"
 #include "tree-vector-builder.h"
 #include "vec-perm-indices.h"
+#include "tree-eh.h"
 
 /* Loop Vectorization Pass.
 
@@ -1063,7 +1064,8 @@ vect_get_loop_niters (struct loop *loop, tree *assumptions,
                                                          may_be_zero));
          else
            niter = fold_build3 (COND_EXPR, TREE_TYPE (niter), may_be_zero,
-                                build_int_cst (TREE_TYPE (niter), 0), niter);
+                                build_int_cst (TREE_TYPE (niter), 0),
+                                rewrite_to_non_trapping_overflow (niter));
 
          may_be_zero = NULL_TREE;
        }