diff options
author | Richard Guenther <rguenther@suse.de> | 2009-04-18 13:02:00 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2009-04-18 13:02:00 +0000 |
commit | 2586ba4bdaaa47413b9c03ff164d926fe52f8dc1 (patch) | |
tree | c7477e42aa4ab8005b7012179ea47e216674f598 /gcc | |
parent | 1eefab17a500e1978e50bdd05c565ed3c607f6b3 (diff) | |
download | gcc-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/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr39804.c | 31 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 3 | ||||
-rw-r--r-- | gcc/tree-ssa-ccp.c | 123 |
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; } |