aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/cse.c29
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr31127.c15
4 files changed, 45 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b90b689..9d2fc89 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2007-03-13 Steven Bosscher <steven@gcc.gnu.org>
+
+ PR middle-end/31127
+ * cse.c (cse_find_path): Do not bail out if a basic block that
+ we already visited now becomes part of a path that starts at a
+ different basic block. Just disallow this, to make sure we
+ visit each basic block at most once.
+
2007-03-13 Jan Hubicka <jh@suse.cz>
* ipa-inline.c (cgraph_maybe_hot_edge_p): Look for hot/cold attributes,
diff --git a/gcc/cse.c b/gcc/cse.c
index 6976d45..cdc5ebe 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -5876,13 +5876,20 @@ cse_find_path (basic_block first_bb, struct cse_basic_block_data *data,
{
bb = FALLTHRU_EDGE (previous_bb_in_path)->dest;
if (bb != EXIT_BLOCK_PTR
- && single_pred_p (bb))
+ && single_pred_p (bb)
+ /* We used to assert here that we would only see blocks
+ that we have not visited yet. But we may end up
+ visiting basic blocks twice if the CFG has changed
+ in this run of cse_main, because when the CFG changes
+ the topological sort of the CFG also changes. A basic
+ blocks that previously had more than two predecessors
+ may now have a single predecessor, and become part of
+ a path that starts at another basic block.
+
+ We still want to visit each basic block only once, so
+ halt the path here if we have already visited BB. */
+ && !TEST_BIT (cse_visited_basic_blocks, bb->index))
{
-#if ENABLE_CHECKING
- /* We should only see blocks here that we have not
- visited yet. */
- gcc_assert (!TEST_BIT (cse_visited_basic_blocks, bb->index));
-#endif
SET_BIT (cse_visited_basic_blocks, bb->index);
data->path[path_size++].bb = bb;
break;
@@ -5921,14 +5928,12 @@ cse_find_path (basic_block first_bb, struct cse_basic_block_data *data,
e = NULL;
if (e && e->dest != EXIT_BLOCK_PTR
- && single_pred_p (e->dest))
+ && single_pred_p (e->dest)
+ /* Avoid visiting basic blocks twice. The large comment
+ above explains why this can happen. */
+ && !TEST_BIT (cse_visited_basic_blocks, e->dest->index))
{
basic_block bb2 = e->dest;
-
- /* We should only see blocks here that we have not
- visited yet. */
- gcc_assert (!TEST_BIT (cse_visited_basic_blocks, bb2->index));
-
SET_BIT (cse_visited_basic_blocks, bb2->index);
data->path[path_size++].bb = bb2;
bb = bb2;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c0358cf..3007d98 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2007-03-13 Alexandre Oliva <aoliva@redhat.com>
+
+ PR middle-end/31127
+ * gcc.dg/pr31127.c: New.
+
2007-03-13 Zdenek Dvorak <dvorakz@suse.cz>
* gcc.dg/tree-ssa/loop-26.c: New test.
diff --git a/gcc/testsuite/gcc.dg/pr31127.c b/gcc/testsuite/gcc.dg/pr31127.c
new file mode 100644
index 0000000..f45b10e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr31127.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void ParseStringSidToSid(char *s, int* p) {
+ int i = 0;
+
+ while (*s) {
+ while (*s && *s != '-')
+ s++;
+ if (*s== '-')
+ s++;
+
+ p[i++] = *s;
+ }
+}