summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr38819.c29
-rw-r--r--gcc/tree-eh.c2
-rw-r--r--gcc/tree-flow.h2
-rw-r--r--gcc/tree-ssa-pre.c9
-rw-r--r--gcc/tree-ssa-sccvn.c47
-rw-r--r--gcc/tree-ssa-sccvn.h1
8 files changed, 105 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 602694cfb5f..1448c0db3a8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 74d88f1128e..43fe9a9396b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..91ae7d82b7c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr38819.c
@@ -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 ();
+}
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 5fe8f24ed27..4e95cf3d66d 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -2067,7 +2067,7 @@ verify_eh_edges (gimple stmt)
/* 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,
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 46578629673..96c098ec376 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -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);
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 0a4fb6ddc10..0717a366bf3 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -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)
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index e40681f9355..78af47ed5eb 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -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;
+}
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index cc74acce10d..74f43c3df2e 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -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);