X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-ssa-loop-ch.c;h=9f1f4c3d0405133f425b6dfcb75068e7d1020508;hb=ca2751b645f00a5ed24db0807acc48a9fcacffc8;hp=378755c9eaa36791a93dc37bfd19a7ce944f2738;hpb=2625ff05d1d2b19e4779319e4370fd69ff15e9f0;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c index 378755c9eaa..9f1f4c3d040 100644 --- a/gcc/tree-ssa-loop-ch.c +++ b/gcc/tree-ssa-loop-ch.c @@ -1,11 +1,11 @@ /* Loop header copying on trees. - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any +Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT @@ -14,9 +14,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -51,14 +50,21 @@ static bool should_duplicate_loop_header_p (basic_block header, struct loop *loop, int *limit) { - block_stmt_iterator bsi; - tree last; + gimple_stmt_iterator bsi; + gimple last; /* Do not copy one block more than once (we do not really want to do loop peeling here). */ if (header->aux) return false; + /* Loop header copying usually increases size of the code. This used not to + be true, since quite often it is possible to verify that the condition is + satisfied in the first iteration and therefore to eliminate it. Jump + threading handles these cases now. */ + if (optimize_loop_for_size_p (loop)) + return false; + gcc_assert (EDGE_COUNT (header->succs) > 0); if (single_succ_p (header)) return false; @@ -72,22 +78,22 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop, return false; last = last_stmt (header); - if (TREE_CODE (last) != COND_EXPR) + if (gimple_code (last) != GIMPLE_COND) return false; /* Approximately copy the conditions that used to be used in jump.c -- at most 20 insns and no calls. */ - for (bsi = bsi_start (header); !bsi_end_p (bsi); bsi_next (&bsi)) + for (bsi = gsi_start_bb (header); !gsi_end_p (bsi); gsi_next (&bsi)) { - last = bsi_stmt (bsi); + last = gsi_stmt (bsi); - if (TREE_CODE (last) == LABEL_EXPR) + if (gimple_code (last) == GIMPLE_LABEL) continue; - if (get_call_expr_in (last)) + if (is_gimple_call (last)) return false; - *limit -= estimate_num_insns (last); + *limit -= estimate_num_insns (last, &eni_size_weights); if (*limit < 0) return false; } @@ -100,17 +106,17 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop, static bool do_while_loop_p (struct loop *loop) { - tree stmt = last_stmt (loop->latch); + gimple stmt = last_stmt (loop->latch); /* If the latch of the loop is not empty, it is not a do-while loop. */ if (stmt - && TREE_CODE (stmt) != LABEL_EXPR) + && gimple_code (stmt) != GIMPLE_LABEL) return false; /* If the header contains just a condition, it is not a do-while loop. */ stmt = last_and_only_stmt (loop->header); if (stmt - && TREE_CODE (stmt) == COND_EXPR) + && gimple_code (stmt) == GIMPLE_COND) return false; return true; @@ -120,11 +126,10 @@ do_while_loop_p (struct loop *loop) of the loop. This is beneficial since it increases efficiency of code motion optimizations. It also saves one jump on entry to the loop. */ -static void +static unsigned int copy_loop_headers (void) { - struct loops *loops; - unsigned i; + loop_iterator li; struct loop *loop; basic_block header; edge exit, entry; @@ -132,30 +137,27 @@ copy_loop_headers (void) unsigned n_bbs; unsigned bbs_size; - loops = loop_optimizer_init (dump_file); - if (!loops) - return; - - /* We do not try to keep the information about irreducible regions - up-to-date. */ - loops->state &= ~LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS; + loop_optimizer_init (LOOPS_HAVE_PREHEADERS + | LOOPS_HAVE_SIMPLE_LATCHES); + if (number_of_loops () <= 1) + { + loop_optimizer_finalize (); + return 0; + } #ifdef ENABLE_CHECKING - verify_loop_structure (loops); + verify_loop_structure (); #endif - bbs = xmalloc (sizeof (basic_block) * n_basic_blocks); - copied_bbs = xmalloc (sizeof (basic_block) * n_basic_blocks); + bbs = XNEWVEC (basic_block, n_basic_blocks); + copied_bbs = XNEWVEC (basic_block, n_basic_blocks); bbs_size = n_basic_blocks; - for (i = 1; i < loops->num; i++) + FOR_EACH_LOOP (li, loop, 0) { /* Copy at most 20 insns. */ int limit = 20; - loop = loops->parray[i]; - if (!loop) - continue; header = loop->header; /* If the loop is already a do-while style one (either because it was @@ -197,26 +199,59 @@ copy_loop_headers (void) /* Ensure that the header will have just the latch as a predecessor inside the loop. */ if (!single_pred_p (exit->dest)) - exit = single_succ_edge (loop_split_edge_with (exit, NULL)); + exit = single_pred_edge (split_edge (exit)); entry = loop_preheader_edge (loop); - if (!tree_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs)) + if (!gimple_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs)) { fprintf (dump_file, "Duplication failed.\n"); continue; } + /* If the loop has the form "for (i = j; i < j + 10; i++)" then + this copying can introduce a case where we rely on undefined + signed overflow to eliminate the preheader condition, because + we assume that "j < j + 10" is true. We don't want to warn + about that case for -Wstrict-overflow, because in general we + don't warn about overflow involving loops. Prevent the + warning by setting the no_warning flag in the condition. */ + if (warn_strict_overflow > 0) + { + unsigned int i; + + for (i = 0; i < n_bbs; ++i) + { + gimple_stmt_iterator bsi; + + for (bsi = gsi_start_bb (copied_bbs[i]); + !gsi_end_p (bsi); + gsi_next (&bsi)) + { + gimple stmt = gsi_stmt (bsi); + if (gimple_code (stmt) == GIMPLE_COND) + gimple_set_no_warning (stmt, true); + else if (is_gimple_assign (stmt)) + { + enum tree_code rhs_code = gimple_assign_rhs_code (stmt); + if (TREE_CODE_CLASS (rhs_code) == tcc_comparison) + gimple_set_no_warning (stmt, true); + } + } + } + } + /* Ensure that the latch and the preheader is simple (we know that they are not now, since there was the loop exit condition. */ - loop_split_edge_with (loop_preheader_edge (loop), NULL); - loop_split_edge_with (loop_latch_edge (loop), NULL); + split_edge (loop_preheader_edge (loop)); + split_edge (loop_latch_edge (loop)); } free (bbs); free (copied_bbs); - loop_optimizer_finalize (loops, NULL); + loop_optimizer_finalize (); + return 0; } static bool @@ -225,8 +260,10 @@ gate_ch (void) return flag_tree_ch != 0; } -struct tree_opt_pass pass_ch = +struct gimple_opt_pass pass_ch = { + { + GIMPLE_PASS, "ch", /* name */ gate_ch, /* gate */ copy_loop_headers, /* execute */ @@ -239,6 +276,6 @@ struct tree_opt_pass pass_ch = 0, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_cleanup_cfg | TODO_dump_func - | TODO_verify_ssa, /* todo_flags_finish */ - 0 /* letter */ + | TODO_verify_ssa /* todo_flags_finish */ + } };