aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2009-04-18 13:02:00 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2009-04-18 13:02:00 +0000
commit2586ba4bdaaa47413b9c03ff164d926fe52f8dc1 (patch)
treec7477e42aa4ab8005b7012179ea47e216674f598 /gcc
parent1eefab17a500e1978e50bdd05c565ed3c607f6b3 (diff)
downloadgcc-2586ba4bdaaa47413b9c03ff164d926fe52f8dc1.zip
gcc-2586ba4bdaaa47413b9c03ff164d926fe52f8dc1.tar.gz
gcc-2586ba4bdaaa47413b9c03ff164d926fe52f8dc1.tar.bz2
re PR tree-optimization/39804 (internal compiler error: in propagate_necessity, at tree-ssa-dce.c:754)
2009-04-18 Richard Guenther <rguenther@suse.de> PR middle-end/39804 * tree-ssa-ccp.c (fold_stmt_1): New function factored from ... (fold_stmt): ... this and ... (fold_stmt_inplace): ... this. (fold_stmt_1): Fold references in calls and asms. * tree-cfg.c (remove_useless_stmts_cond): Use fold_stmt. * gcc.target/i386/pr39804.c: New testcase. From-SVN: r146314
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr39804.c31
-rw-r--r--gcc/tree-cfg.c3
-rw-r--r--gcc/tree-ssa-ccp.c123
5 files changed, 113 insertions, 58 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 49608da..19806f5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2009-04-18 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/39804
+ * tree-ssa-ccp.c (fold_stmt_1): New function factored from ...
+ (fold_stmt): ... this and ...
+ (fold_stmt_inplace): ... this.
+ (fold_stmt_1): Fold references in calls and asms.
+ * tree-cfg.c (remove_useless_stmts_cond): Use fold_stmt.
+
2009-04-18 Kazu Hirata <kazu@codesourcery.com>
* tree-vrp.c (ssa_name_nonzero_p): Remove.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4085037..846725e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-04-18 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/39804
+ * gcc.target/i386/pr39804.c: New testcase.
+
2009-04-18 Eric Botcazou <ebotcazou@adacore.com>
* gcc.target/i386/pr39496.c: Compile with -mtune=i686.
diff --git a/gcc/testsuite/gcc.target/i386/pr39804.c b/gcc/testsuite/gcc.target/i386/pr39804.c
new file mode 100644
index 0000000..3ff2479
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr39804.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O" } */
+
+typedef unsigned char u8;
+struct __large_struct { unsigned long buf[100]; };
+static inline __attribute__((always_inline)) unsigned long
+__copy_from_user_inatomic(void *to, const void *from, unsigned long n)
+{
+ unsigned long ret = 0;
+ asm volatile("1: mov""b"" %2,%""b""1\n" "2:\n"
+ ".section .fixup,\"ax\"\n"
+ "3: mov %3,%0\n"
+ " xor""b"" %""b""1,%""b""1\n"
+ " jmp 2b\n"
+ ".previous\n"
+ " .section __ex_table,\"a\"\n"
+ " " ".balign 4" " " "\n"
+ " " ".long" " " "1b" "," "3b" "\n"
+ " .previous\n"
+ : "=r" (ret), "=q"(*(u8 *)to)
+ : "m" ((*(struct __large_struct *)(from))), "i" (1), "0" (ret));
+ return ret;
+}
+void romchecksum(const unsigned char *rom, unsigned char c)
+{
+ unsigned char sum;
+ for (sum = 0;
+ !__copy_from_user_inatomic(&(c), ( typeof(c) *)(rom++), sizeof(c));)
+ sum += c;
+}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 9862af8..d4aa935 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -1574,7 +1574,8 @@ remove_useless_stmts_cond (gimple_stmt_iterator *gsi, struct rus_data *data)
gimple stmt = gsi_stmt (*gsi);
/* The folded result must still be a conditional statement. */
- fold_stmt_inplace (stmt);
+ fold_stmt (gsi);
+ gcc_assert (gsi_stmt (*gsi) == stmt);
data->may_branch = true;
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 0bbc0f0..9cf2f83 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -2836,43 +2836,81 @@ fold_gimple_call (gimple_stmt_iterator *gsi)
return false;
}
-/* Fold the statement pointed to by GSI. In some cases, this function may
- replace the whole statement with a new one. Returns true iff folding
- makes any changes.
- The statement pointed to by GSI should be in valid gimple form but may
- be in unfolded state as resulting from for example constant propagation
- which can produce *&x = 0. */
+/* Worker for both fold_stmt and fold_stmt_inplace. The INPLACE argument
+ distinguishes both cases. */
-bool
-fold_stmt (gimple_stmt_iterator *gsi)
+static bool
+fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace)
{
bool changed = false;
gimple stmt = gsi_stmt (*gsi);
+ unsigned i;
/* Fold the main computation performed by the statement. */
switch (gimple_code (stmt))
{
case GIMPLE_ASSIGN:
{
+ unsigned old_num_ops = gimple_num_ops (stmt);
tree new_rhs = fold_gimple_assign (gsi);
- if (new_rhs != NULL_TREE)
+ if (new_rhs != NULL_TREE
+ && (!inplace
+ || get_gimple_rhs_num_ops (TREE_CODE (new_rhs)) < old_num_ops))
{
gimple_assign_set_rhs_from_tree (gsi, new_rhs);
changed = true;
}
break;
}
+
case GIMPLE_COND:
changed |= fold_gimple_cond (stmt);
break;
+
case GIMPLE_CALL:
+ /* Fold *& in call arguments. */
+ for (i = 0; i < gimple_call_num_args (stmt); ++i)
+ if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i)))
+ {
+ tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i), false);
+ if (tmp)
+ {
+ gimple_call_set_arg (stmt, i, tmp);
+ changed = true;
+ }
+ }
/* The entire statement may be replaced in this case. */
- changed |= fold_gimple_call (gsi);
+ if (!inplace)
+ changed |= fold_gimple_call (gsi);
break;
- default:
- return changed;
+ case GIMPLE_ASM:
+ /* Fold *& in asm operands. */
+ for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
+ {
+ tree link = gimple_asm_output_op (stmt, i);
+ tree op = TREE_VALUE (link);
+ if (REFERENCE_CLASS_P (op)
+ && (op = maybe_fold_reference (op, true)) != NULL_TREE)
+ {
+ TREE_VALUE (link) = op;
+ changed = true;
+ }
+ }
+ for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
+ {
+ tree link = gimple_asm_input_op (stmt, i);
+ tree op = TREE_VALUE (link);
+ if (REFERENCE_CLASS_P (op)
+ && (op = maybe_fold_reference (op, false)) != NULL_TREE)
+ {
+ TREE_VALUE (link) = op;
+ changed = true;
+ }
+ }
break;
+
+ default:;
}
stmt = gsi_stmt (*gsi);
@@ -2895,6 +2933,19 @@ fold_stmt (gimple_stmt_iterator *gsi)
return changed;
}
+/* Fold the statement pointed to by GSI. In some cases, this function may
+ replace the whole statement with a new one. Returns true iff folding
+ makes any changes.
+ The statement pointed to by GSI should be in valid gimple form but may
+ be in unfolded state as resulting from for example constant propagation
+ which can produce *&x = 0. */
+
+bool
+fold_stmt (gimple_stmt_iterator *gsi)
+{
+ return fold_stmt_1 (gsi, false);
+}
+
/* Perform the minimal folding on statement STMT. Only operations like
*&x created by constant propagation are handled. The statement cannot
be replaced with a new one. Return true if the statement was
@@ -2906,51 +2957,9 @@ fold_stmt (gimple_stmt_iterator *gsi)
bool
fold_stmt_inplace (gimple stmt)
{
- gimple_stmt_iterator si;
- bool changed = false;
-
- /* Fold the main computation performed by the statement. */
- switch (gimple_code (stmt))
- {
- case GIMPLE_ASSIGN:
- {
- unsigned old_num_ops;
- tree new_rhs;
- old_num_ops = gimple_num_ops (stmt);
- si = gsi_for_stmt (stmt);
- new_rhs = fold_gimple_assign (&si);
- if (new_rhs != NULL_TREE
- && get_gimple_rhs_num_ops (TREE_CODE (new_rhs)) < old_num_ops)
- {
- gimple_assign_set_rhs_from_tree (&si, new_rhs);
- changed = true;
- }
- gcc_assert (gsi_stmt (si) == stmt);
- break;
- }
- case GIMPLE_COND:
- changed |= fold_gimple_cond (stmt);
- break;
-
- default:
- break;
- }
-
- /* Fold *& on the lhs. */
- if (gimple_has_lhs (stmt))
- {
- tree lhs = gimple_get_lhs (stmt);
- if (lhs && REFERENCE_CLASS_P (lhs))
- {
- tree new_lhs = maybe_fold_reference (lhs, true);
- if (new_lhs)
- {
- gimple_set_lhs (stmt, new_lhs);
- changed = true;
- }
- }
- }
-
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ bool changed = fold_stmt_1 (&gsi, true);
+ gcc_assert (gsi_stmt (gsi) == stmt);
return changed;
}