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 + + 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 * 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 + + PR tree-optimization/52808 + * gcc.dg/pr52808.c: New testcase. + 2012-04-03 Jakub Jelinek 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;