]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/38819 (trapping expression wrongly hoisted out of loop)
authorRichard Guenther <rguenther@suse.de>
Sun, 18 Jan 2009 15:51:12 +0000 (15:51 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Sun, 18 Jan 2009 15:51:12 +0000 (15:51 +0000)
2009-01-18  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/38819
* tree-flow.h (operation_could_trap_helper_p): Declare.
* tree-eh.c (operation_could_trap_helper_p): Export.
* tree-ssa-sccvn.h (vn_nary_may_trap): Declare.
* tree-ssa-sccvn.c (vn_nary_may_trap): New function.
* tree-ssa-pre.c (insert_into_preds_of_block): Check if we
are about to insert a possibly trapping instruction and fail
in this case.

* gcc.c-torture/execute/pr38819.c: New testcase.

From-SVN: r143485

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr38819.c [new file with mode: 0644]
gcc/tree-eh.c
gcc/tree-flow.h
gcc/tree-ssa-pre.c
gcc/tree-ssa-sccvn.c
gcc/tree-ssa-sccvn.h

index 602694cfb5f6868221c2cbf8086da1ba242b6c62..1448c0db3a86d22670a07880eb2c66f7967d969c 100644 (file)
@@ -1,3 +1,14 @@
+2009-01-18  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/38819
+       * tree-flow.h (operation_could_trap_helper_p): Declare.
+       * tree-eh.c (operation_could_trap_helper_p): Export.
+       * tree-ssa-sccvn.h (vn_nary_may_trap): Declare.
+       * tree-ssa-sccvn.c (vn_nary_may_trap): New function.
+       * tree-ssa-pre.c (insert_into_preds_of_block): Check if we
+       are about to insert a possibly trapping instruction and fail
+       in this case.
+
 2009-01-18  Andreas Schwab  <schwab@suse.de>
 
        * doc/install.texi (Configuration): Remove obsolete paragraph
index 74d88f1128e1950c04c8d3b046ed220b37f9e1c2..43fe9a9396bb7a72a226058af30ea2680d45bb11 100644 (file)
@@ -1,3 +1,8 @@
+2009-01-18  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/38819
+       * gcc.c-torture/execute/pr38819.c: New testcase.
+
 2009-01-17  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/38657
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr38819.c b/gcc/testsuite/gcc.c-torture/execute/pr38819.c
new file mode 100644 (file)
index 0000000..91ae7d8
--- /dev/null
@@ -0,0 +1,29 @@
+extern void exit (int);
+extern void abort (void);
+
+volatile int a = 1;
+volatile int b = 0;
+volatile int x = 2;
+volatile signed int r = 8;
+
+void __attribute__((noinline))
+foo (void)
+{
+  exit (0);
+}
+
+int
+main (void)
+{
+  int si1 = a;
+  int si2 = b;
+  int i;
+
+  for (i = 0; i < 100; ++i) {
+      foo ();
+      if (x == 8)
+       i++;
+      r += i + si1 % si2;
+  }
+  abort ();
+}
index 5fe8f24ed27149676bffb0188af817a163365f85..4e95cf3d66db6c0bd8f257d694300b069aabd5fe 100644 (file)
@@ -2067,7 +2067,7 @@ verify_eh_edges (gimple stmt)
 \f
 /* Helper function for operation_could_trap_p and stmt_could_throw_p.  */
 
-static bool
+bool
 operation_could_trap_helper_p (enum tree_code op,
                               bool fp_operation,
                               bool honor_trapv,
index 4657862967347ef45a77aa1e17cd5ff471e88fdc..96c098ec3763834df9e3ebc732534e031fe40c16 100644 (file)
@@ -1071,6 +1071,8 @@ static inline bool unmodifiable_var_p (const_tree);
 /* In tree-eh.c  */
 extern void make_eh_edges (gimple);
 extern bool tree_could_trap_p (tree);
+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 stmt_could_throw_p (gimple);
 extern bool tree_could_throw_p (tree);
index 0a4fb6ddc101b61ca0cdd5382188b418afdb4433..0717a366bf380b6ab8d6fa78615374ed55dae69f 100644 (file)
@@ -3004,6 +3004,15 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
        }
     }
 
+  /* Make sure we are not inserting trapping expressions.  */
+  FOR_EACH_EDGE (pred, ei, block->preds)
+    {
+      bprime = pred->src;
+      eprime = avail[bprime->index];
+      if (eprime->kind == NARY
+         && vn_nary_may_trap (PRE_EXPR_NARY (eprime)))
+       return false;
+    }
 
   /* Make the necessary insertions.  */
   FOR_EACH_EDGE (pred, ei, block->preds)
index e40681f935546c05b2eb7bd0204ac2b60d505e96..78af47ed5ebca88cf654b5331da119783e982ad8 100644 (file)
@@ -3072,3 +3072,50 @@ sort_vuses_heap (VEC (tree,heap) *vuses)
           sizeof (tree),
           operand_build_cmp);
 }
+
+
+/* Return true if the nary operation NARY may trap.  This is a copy
+   of stmt_could_throw_1_p adjusted to the SCCVN IL.  */
+
+bool
+vn_nary_may_trap (vn_nary_op_t nary)
+{
+  tree type;
+  tree rhs2;
+  bool honor_nans = false;
+  bool honor_snans = false;
+  bool fp_operation = false;
+  bool honor_trapv = false;
+  bool handled, ret;
+  unsigned i;
+
+  if (TREE_CODE_CLASS (nary->opcode) == tcc_comparison
+      || TREE_CODE_CLASS (nary->opcode) == tcc_unary
+      || TREE_CODE_CLASS (nary->opcode) == tcc_binary)
+    {
+      type = nary->type;
+      fp_operation = FLOAT_TYPE_P (type);
+      if (fp_operation)
+       {
+         honor_nans = flag_trapping_math && !flag_finite_math_only;
+         honor_snans = flag_signaling_nans != 0;
+       }
+      else if (INTEGRAL_TYPE_P (type)
+              && TYPE_OVERFLOW_TRAPS (type))
+       honor_trapv = true;
+    }
+  rhs2 = nary->op[1];
+  ret = operation_could_trap_helper_p (nary->opcode, fp_operation,
+                                      honor_trapv,
+                                      honor_nans, honor_snans, rhs2,
+                                      &handled);
+  if (handled
+      && ret)
+    return true;
+
+  for (i = 0; i < nary->length; ++i)
+    if (tree_could_trap_p (nary->op[i]))
+      return true;
+
+  return false;
+}
index cc74acce10da37aa2577c2f7d00bc9f7cf192fd7..74f43c3df2ea429af0337f8a3b97fed3fcc701a5 100644 (file)
@@ -188,6 +188,7 @@ tree vn_phi_lookup (gimple);
 
 hashval_t vn_nary_op_compute_hash (const vn_nary_op_t);
 int vn_nary_op_eq (const void *, const void *);
+bool vn_nary_may_trap (vn_nary_op_t);
 hashval_t vn_reference_compute_hash (const vn_reference_t);
 int vn_reference_eq (const void *, const void *);
 unsigned int get_max_value_id (void);