summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-03 11:38:04 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-03 11:38:04 +0000
commit35c67c833b78806f818339542f2db310b18349bd (patch)
tree89c43a99b22d5e7d34c2934ec55d1719cf2bab3a /gcc
parentbc05341c10553db8c7abbe942dc5f6e683450a24 (diff)
downloadgcc-35c67c833b78806f818339542f2db310b18349bd.tar.gz
2012-04-03 Richard Guenther <rguenther@suse.de>
PR tree-optimization/52808 * tracer.c (tail_duplicate): Return whether we have duplicated any block. (tracer): If we have duplicated any block, cleanup the CFG. * cfghooks.c (duplicate_block): If we duplicated a loop header but not its loop, destroy the loop because it now has multiple entries. * tree-ssa-threadupdate.c (thread_through_loop_header): Tell the cfg manipulation routines we are not creating a multiple entry loop. * gcc.dg/pr52808.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186104 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/cfghooks.c28
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr52808.c12
-rw-r--r--gcc/tracer.c18
-rw-r--r--gcc/tree-ssa-threadupdate.c6
6 files changed, 65 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7c1d1b3bb20..74a5a184811 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2012-04-03 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/52808
+ * tracer.c (tail_duplicate): Return whether we have duplicated
+ any block.
+ (tracer): If we have duplicated any block, cleanup the CFG.
+ * cfghooks.c (duplicate_block): If we duplicated a loop
+ header but not its loop, destroy the loop because it now has
+ multiple entries.
+ * tree-ssa-threadupdate.c (thread_through_loop_header): Tell
+ the cfg manipulation routines we are not creating a multiple
+ entry loop.
+
2012-04-03 Tristan Gingold <gingold@adacore.com>
* config/vms/vms-c.c (vms_pragma_nomember_alignment): Handle
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index 1dca79a70cf..bc1b7a2f582 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -1009,18 +1009,28 @@ duplicate_block (basic_block bb, edge e, basic_block after)
{
struct loop *cloop = bb->loop_father;
struct loop *copy = get_loop_copy (cloop);
- add_bb_to_loop (new_bb, copy ? copy : cloop);
- /* If we copied the loop latch block but not the loop, adjust
- loop state.
- ??? If we copied the loop header block but not the loop
- we might either have created a loop copy or a loop with
- multiple entries. In both cases we probably have to
- ditch the loops and arrange for a fixup. */
+ /* If we copied the loop header block but not the loop
+ we have created a loop with multiple entries. Ditch the loop,
+ add the new block to the outer loop and arrange for a fixup. */
if (!copy
- && cloop->latch == bb)
+ && cloop->header == bb)
{
+ add_bb_to_loop (new_bb, loop_outer (cloop));
+ cloop->header = NULL;
cloop->latch = NULL;
- loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
+ loops_state_set (LOOPS_NEED_FIXUP);
+ }
+ else
+ {
+ add_bb_to_loop (new_bb, copy ? copy : cloop);
+ /* If we copied the loop latch block but not the loop, adjust
+ loop state. */
+ if (!copy
+ && cloop->latch == bb)
+ {
+ cloop->latch = NULL;
+ loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
+ }
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7fe8a18ca0f..c757d42d177 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-04-03 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/52808
+ * gcc.dg/pr52808.c: New testcase.
+
2012-04-03 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/52835
diff --git a/gcc/testsuite/gcc.dg/pr52808.c b/gcc/testsuite/gcc.dg/pr52808.c
new file mode 100644
index 00000000000..b731cb40133
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr52808.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O -ftracer" } */
+
+int **fn1 () __attribute__ ((__const__));
+int main ()
+{
+ int i;
+ i = 0;
+ for (;; i++)
+ if (*fn1 ()[i] && !'a' <= 0 && i <= 'z' || *fn1 ()[0] && 'a' <= 'z')
+ return;
+}
diff --git a/gcc/tracer.c b/gcc/tracer.c
index 602e7580d99..8fb9817dbe9 100644
--- a/gcc/tracer.c
+++ b/gcc/tracer.c
@@ -59,7 +59,6 @@ static bool better_p (const_edge, const_edge);
static edge find_best_successor (basic_block);
static edge find_best_predecessor (basic_block);
static int find_trace (basic_block, basic_block *);
-static void tail_duplicate (void);
/* Minimal outgoing edge probability considered for superblock formation. */
static int probability_cutoff;
@@ -224,7 +223,7 @@ find_trace (basic_block bb, basic_block *trace)
/* Look for basic blocks in frequency order, construct traces and tail duplicate
if profitable. */
-static void
+static bool
tail_duplicate (void)
{
fibnode_t *blocks = XCNEWVEC (fibnode_t, last_basic_block);
@@ -236,6 +235,7 @@ tail_duplicate (void)
gcov_type cover_insns;
int max_dup_insns;
basic_block bb;
+ bool changed = false;
/* Create an oversized sbitmap to reduce the chance that we need to
resize it. */
@@ -332,6 +332,7 @@ tail_duplicate (void)
bb2->index, copy->index, copy->frequency);
bb2 = copy;
+ changed = true;
}
mark_bb_seen (bb2);
bb = bb2;
@@ -353,6 +354,8 @@ tail_duplicate (void)
free (trace);
free (counts);
fibheap_delete (heap);
+
+ return changed;
}
/* Main entry point to this file. */
@@ -360,6 +363,8 @@ tail_duplicate (void)
static unsigned int
tracer (void)
{
+ bool changed;
+
gcc_assert (current_ir_type () == IR_GIMPLE);
if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
@@ -370,15 +375,14 @@ tracer (void)
dump_flow_info (dump_file, dump_flags);
/* Trace formation is done on the fly inside tail_duplicate */
- tail_duplicate ();
+ changed = tail_duplicate ();
+ if (changed)
+ free_dominance_info (CDI_DOMINATORS);
- /* FIXME: We really only need to do this when we know tail duplication
- has altered the CFG. */
- free_dominance_info (CDI_DOMINATORS);
if (dump_file)
dump_flow_info (dump_file, dump_flags);
- return 0;
+ return changed ? TODO_cleanup_cfg : 0;
}
static bool
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index 000bd3f2e40..687eee0485a 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -1004,8 +1004,12 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
basic_block *bblocks;
unsigned nblocks, i;
- /* First handle the case latch edge is redirected. */
+ /* First handle the case latch edge is redirected. We are copying
+ the loop header but not creating a multiple entry loop. Make the
+ cfg manipulation code aware of that fact. */
+ set_loop_copy (loop, loop);
loop->latch = thread_single_edge (latch);
+ set_loop_copy (loop, NULL);
gcc_assert (single_succ (loop->latch) == tgt_bb);
loop->header = tgt_bb;