We still have some lno bits in our tree. We tried to remove them and
found:
gzip +0.5%
vpr -0.4%
gcc -3.2%
mcf -0.3%
crafty +0.2%
parser +0.2%
perlbmk -2.2%
gap +0.2%
vortex -0.1%
bzip2 +1.9%
twolf -0.7%
on x86 (probably a core2 duo) in our 4.2 tree (with the rest of our
local patches). -3.2% means a 3.2% better codegen (roughly) with the
lno bits. I didn't rerun the numbers for mainline to see if they are
still applicable.
Of all the LNO bits, the last major bits seems to be the below bit.
I don't even know if it is responsible for the benefit we see. I
thought I'd mention it, as a 2-3% win on two of the spec tests seems
worthwhile.
I'd be interested in finding someone that might be interested in
tracking down where the benefit comes from in the patch and pushing
into mainline what goodness there is to be had from the patch. Any
takers? If I can find someone, I'd be happy to send out the version
of the patch for mainline. [ hum just 567 lines] On second though,
I'll just include at the end for reference. Note, there is one soft
conflict resolution to resolve in going from the 4.2 context to
mainline, which I've not yet resolved.
2004-07-13 Zdenek Dvorak <[EMAIL PROTECTED]>
* Makefile.in (tree-ssa-loop.o, tree-ssa-dce.o): Add function.h
dependency.
* builtins.c (expand_builtin): Handle
BUILT_IN_MAYBE_INFINITE_LOOP.
* builtins.def (BUILT_IN_MAYBE_INFINITE_LOOP): New builtin.
* function.h (struct function): Add marked_maybe_inf_loops
field.
* timevar.def (TV_MARK_MILOOPS): New timevar.
* tree-flow.h (mark_maybe_infinite_loops): Declare.
* tree-optimize.c (init_tree_optimization_passes): Add
pass_mark_maybe_inf_loops.
* tree-pass.h (pass_mark_maybe_inf_loops): Declare.
* tree-ssa-dce.c: Include function.h.
(find_obviously_necessary_stmts): Mark back edges only if
they were
not marked already.
(perform_tree_ssa_dce): Do not call mark_dfs_back_edges here.
* tree-ssa-loop-niter.c (unmark_surely_finite_loop,
mark_maybe_infinite_loops): New functions.
* tree-ssa-loop.c: Include function.h.
(tree_mark_maybe_inf_loops, gate_tree_mark_maybe_inf_loops,
pass_mark_maybe_inf_loops): New pass.
* tree-ssa-operands.c (function_ignores_memory_p): Add
BUILT_IN_MAYBE_INFINITE_LOOP.
Doing diffs in .:
--- ./builtins.c.~1~ 2007-04-13 10:06:18.000000000 -0700
+++ ./builtins.c 2007-04-21 15:54:01.000000000 -0700
@@ -6562,6 +6562,12 @@ expand_builtin (tree exp, rtx target, rt
return target;
break;
+ /* APPLE LOCAL begin lno */
+ case BUILT_IN_MAYBE_INFINITE_LOOP:
+ /* This is just a fake statement that expands to nothing. */
+ return const0_rtx;
+ /* APPLE LOCAL end lno */
+
case BUILT_IN_FETCH_AND_ADD_1:
case BUILT_IN_FETCH_AND_ADD_2:
case BUILT_IN_FETCH_AND_ADD_4:
--- ./builtins.def.~1~ 2007-04-13 10:06:19.000000000 -0700
+++ ./builtins.def 2007-04-21 15:54:01.000000000 -0700
@@ -639,6 +639,8 @@ DEF_LIB_BUILTIN (BUILT_IN_FREE, "
DEF_GCC_BUILTIN (BUILT_IN_FROB_RETURN_ADDR, "frob_return_addr",
BT_FN_PTR_PTR, ATTR_NULL)
DEF_EXT_LIB_BUILTIN (BUILT_IN_GETTEXT, "gettext",
BT_FN_STRING_CONST_STRING, ATTR_FORMAT_ARG_1)
DEF_C99_BUILTIN (BUILT_IN_IMAXABS, "imaxabs", BT_FN_INTMAX_INTMAX,
ATTR_CONST_NOTHROW_LIST)
+/* APPLE LOCAL lno */
+DEF_GCC_BUILTIN (BUILT_IN_MAYBE_INFINITE_LOOP, "maybe_infinite_loop",
BT_FN_VOID, ATTR_NULL)
DEF_GCC_BUILTIN (BUILT_IN_INIT_DWARF_REG_SIZES,
"init_dwarf_reg_size_table", BT_FN_VOID_PTR, ATTR_NULL)
DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITE, "finite", BT_FN_INT_DOUBLE,
ATTR_CONST_NOTHROW_LIST)
DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITEF, "finitef", BT_FN_INT_FLOAT,
ATTR_CONST_NOTHROW_LIST)
--- ./cfghooks.c.~1~ 2007-02-12 20:10:38.000000000 -0800
+++ ./cfghooks.c 2007-04-21 15:59:31.000000000 -0700
@@ -405,6 +405,10 @@ edge
split_block (basic_block bb, void *i)
{
basic_block new_bb;
+ /* APPLE LOCAL begin lno */
+ bool irr = (bb->flags & BB_IRREDUCIBLE_LOOP) != 0;
+ int flags = EDGE_FALLTHRU;
+ /* APPLE LOCAL end lno */
if (!cfg_hooks->split_block)
internal_error ("%s does not support split_block", cfg_hooks->name);
@@ -416,6 +420,13 @@ split_block (basic_block bb, void *i)
new_bb->count = bb->count;
new_bb->frequency = bb->frequency;
new_bb->loop_depth = bb->loop_depth;
+ /* APPLE LOCAL begin lno */
+ if (irr)
+ {
+ new_bb->flags |= BB_IRREDUCIBLE_LOOP;
+ flags |= EDGE_IRREDUCIBLE_LOOP;
+ }
+ /* APPLE LOCAL end lno */
if (dom_info_available_p (CDI_DOMINATORS))
{
@@ -560,6 +571,15 @@ split_edge (edge e)
}
}
+ /* APPLE LOCAL begin lno */
+ if (irr)
+ {
+ ret->flags |= BB_IRREDUCIBLE_LOOP;
+ EDGE_PRED (ret, 0)->flags |= EDGE_IRREDUCIBLE_LOOP;
+ EDGE_SUCC (ret, 0)->flags |= EDGE_IRREDUCIBLE_LOOP;
+ }
+ /* APPLE LOCAL end lno */
+
if (current_loops != NULL)
{
loop = find_common_loop (src->loop_father, dest->loop_father);
@@ -698,6 +718,8 @@ make_forwarder_block (basic_block bb, bo
edge e, fallthru;
edge_iterator ei;
basic_block dummy, jump;
+ /* APPLE LOCAL lno */
+ bool fst_irr = false;
struct loop *loop, *ploop, *cloop;
if (!cfg_hooks->make_forwarder_block)
@@ -713,6 +735,8 @@ make_forwarder_block (basic_block bb, bo
{
if (redirect_edge_p (e))
{
+ /* APPLE LOCAL lno */
+ fst_irr |= (e->flags & EDGE_IRREDUCIBLE_LOOP) != 0;
ei_next (&ei);
continue;
}
@@ -733,6 +757,14 @@ make_forwarder_block (basic_block bb, bo
new_bb_cbk (jump);
}
+ /* APPLE LOCAL begin lno */
+ if (!fst_irr)
+ {
+ dummy->flags &= ~BB_IRREDUCIBLE_LOOP;
+ fallthru->flags &= ~EDGE_IRREDUCIBLE_LOOP;
+ }
+ /* APPLE LOCAL end lno */
+
if (dom_info_available_p (CDI_DOMINATORS))
{
basic_block doms_to_fix[2];
--- ./cfgloop.c.~1~ 2007-04-13 10:06:20.000000000 -0700
+++ ./cfgloop.c 2007-04-21 15:54:01.000000000 -0700
@@ -484,7 +484,13 @@ flow_loops_find (struct loops *loops)
free (dfs_order);
free (rc_order);
+ /* APPLE LOCAL begin lno */
}
+ else
+ {
+ free_dominance_info (CDI_DOMINATORS);
+ }
+ /* APPLE LOCAL end lno */
sbitmap_free (headers);
--- ./cfgrtl.c.~1~ 2007-03-20 19:07:01.000000000 -0700
+++ ./cfgrtl.c 2007-04-21 15:54:01.000000000 -0700
@@ -2104,6 +2104,14 @@ purge_dead_edges (basic_block bb)
&& (! (e->flags & EDGE_ABNORMAL_CALL)
|| CALL_P (BB_END (bb))))
{
+ /* APPLE LOCAL begin lno */
+ /* If the call was removed/moved somewhere else, cleanup the
+ EDGE_ABNORMAL_CALL flag. */
+ if ((e->flags & EDGE_ABNORMAL_CALL)
+ && GET_CODE (BB_END (bb)) != CALL_INSN)
+ e->flags &= ~EDGE_ABNORMAL_CALL;
+ /* APPLE LOCAL end lno */
+
ei_next (&ei);
continue;
}
--- ./doc/invoke.texi.~1~ 2007-04-21 15:48:05.000000000 -0700
+++ ./doc/invoke.texi 2007-04-21 15:54:05.000000000 -0700
@@ -280,6 +280,11 @@ Objective-C and Objective-C++ Dialects}.
[EMAIL PROTECTED]@[EMAIL PROTECTED] [EMAIL PROTECTED]@[EMAIL PROTECTED] @gol
[EMAIL PROTECTED]@[EMAIL PROTECTED] [EMAIL PROTECTED]@[EMAIL PROTECTED] @gol
[EMAIL PROTECTED]@r{]} [EMAIL PROTECTED]@[EMAIL PROTECTED] @gol
[EMAIL PROTECTED] APPLE LOCAL begin lno
+-fdump-tree-scev @[EMAIL PROTECTED]@r{]} @gol
+-fdump-tree-ddall @[EMAIL PROTECTED]@[EMAIL PROTECTED]
+-fdump-tree-elck @[EMAIL PROTECTED]@r{]} @gol
[EMAIL PROTECTED] APPLE LOCAL end lno
[EMAIL PROTECTED]@[EMAIL PROTECTED] @gol
[EMAIL PROTECTED]@[EMAIL PROTECTED] @gol
[EMAIL PROTECTED]@[EMAIL PROTECTED] @gol
@@ -290,6 +295,10 @@ Objective-C and Objective-C++ Dialects}.
[EMAIL PROTECTED]@[EMAIL PROTECTED] @gol
-fdump-tree-salias @gol
[EMAIL PROTECTED]@[EMAIL PROTECTED] @gol
[EMAIL PROTECTED] APPLE LOCAL begin lno
[EMAIL PROTECTED]@[EMAIL PROTECTED] @gol
[EMAIL PROTECTED]@[EMAIL PROTECTED] @gol
[EMAIL PROTECTED] APPLE LOCAL end lno
[EMAIL PROTECTED]@[EMAIL PROTECTED] @gol
[EMAIL PROTECTED] @gol
[EMAIL PROTECTED]@[EMAIL PROTECTED] @gol
@@ -358,6 +367,8 @@ Objective-C and Objective-C++ Dialects}.
-ftree-ch -ftree-sra -ftree-ter -ftree-fre -ftree-vectorize @gol
-ftree-vect-loop-version -ftree-salias -fipa-pta -fweb @gol
-ftree-copy-prop -ftree-store-ccp -ftree-store-copy-prop -fwhole-program @gol
[EMAIL PROTECTED] APPLE LOCAL lno
+-fscalar-evolutions -fall-data-deps @gol
--param @[EMAIL PROTECTED]
-O -O0 -O1 -O2 -O3 -Os}
@@ -4609,6 +4620,24 @@ appending @file{.dce} to the source file
Dump each function after adding mudflap instrumentation. The file name is
made by appending @file{.mudflap} to the source file name.
[EMAIL PROTECTED] APPLE LOCAL begin lno
[EMAIL PROTECTED] scev
[EMAIL PROTECTED] fdump-tree-scev
+Dump the information gathered by the scalar evolution analyzer.
+The file name is made by appending @file{.scev} to the source file name.
+
[EMAIL PROTECTED] ddall
[EMAIL PROTECTED] fdump-tree-ddall
+Dump all the data dependence relations.
+The file name is made by appending @file{.ddall} to the source file name.
+
[EMAIL PROTECTED] elck
[EMAIL PROTECTED] fdump-tree-elck
+Dump each function after performing checks elimination based on scalar
+evolution informations. The file name is made by appending
[EMAIL PROTECTED] to the source file name.
[EMAIL PROTECTED] APPLE LOCAL end lno
+
@item sra
@opindex fdump-tree-sra
Dump each function after performing scalar replacement of aggregates. The
@@ -4650,6 +4679,13 @@ Dump each function after applying the na
generic trees. The file name is made by appending @file{.nrv} to the source
file name.
[EMAIL PROTECTED] APPLE LOCAL begin lno
[EMAIL PROTECTED] loop
[EMAIL PROTECTED] fdump-tree-loop
+Dump each function after applying tree-level loop optimizations. The file
+name is made by appending @file{.loop} to the source file name.
[EMAIL PROTECTED] APPLE LOCAL end lno
+
@item vect
@opindex fdump-tree-vect
Dump each function after applying vectorization of loops. The file name is
@@ -5550,6 +5586,12 @@ effectiveness of code motion optimizatio
is enabled by default at @option{-O} and higher. It is not enabled
for @option{-Os}, since it usually increases code size.
[EMAIL PROTECTED] APPLE LOCAL begin lno
[EMAIL PROTECTED] -ftree-elim-checks
+Perform elimination of checks based on scalar evolution informations.
+This flag is disabled by default.
[EMAIL PROTECTED] APPLE LOCAL end lno
+
@item -ftree-loop-optimize
Perform loop optimizations on trees. This flag is enabled by default
at @option{-O} and higher.
--- ./fortran/f95-lang.c.~1~ 2007-04-21 15:48:07.000000000 -0700
+++ ./fortran/f95-lang.c 2007-04-21 15:54:05.000000000 -0700
@@ -989,6 +989,12 @@ gfc_init_builtin_functions (void)
ftype = build_function_type (long_integer_type_node, tmp);
gfc_define_builtin ("__builtin_expect", ftype, BUILT_IN_EXPECT,
"__builtin_expect", true);
+ /* APPLE LOCAL begin lno */
+ ftype = build_function_type (void_type_node, void_list_node);
+ gfc_define_builtin ("__builtin_maybe_infinite_loop", ftype,
+ BUILT_IN_MAYBE_INFINITE_LOOP, "maybe_infinite_loop",
+ false);
+ /* APPLE LOCAL end lno */
#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
builtin_types[(int) ENUM] = VALUE;
--- ./java/builtins.c.~1~ 2007-02-15 18:23:31.000000000 -0800
+++ ./java/builtins.c 2007-04-21 15:54:05.000000000 -0700
@@ -467,6 +467,8 @@ initialize_builtins (void)
{
tree double_ftype_double, double_ftype_double_double;
tree float_ftype_float, float_ftype_float_float;
+ /* APPLE LOCAL lno */
+ tree void_ftype;
tree boolean_ftype_boolean_boolean;
tree t;
int i;
@@ -492,6 +494,10 @@ initialize_builtins (void)
t = tree_cons (NULL_TREE, double_type_node, t);
double_ftype_double_double = build_function_type (double_type_node, t);
+ /* APPLE LOCAL begin lno */
+ void_ftype = build_function_type (void_type_node, NULL_TREE);
+ /* APPLE LOCAL end lno */
+
define_builtin (BUILT_IN_FMOD, "__builtin_fmod",
double_ftype_double_double, "fmod", BUILTIN_CONST);
define_builtin (BUILT_IN_FMODF, "__builtin_fmodf",
@@ -536,6 +542,10 @@ initialize_builtins (void)
define_builtin (BUILT_IN_TAN, "__builtin_tan",
double_ftype_double, "_ZN4java4lang4Math3tanEJdd",
BUILTIN_CONST);
+ /* APPLE LOCAL begin lno */
+ define_builtin (BUILT_IN_MAYBE_INFINITE_LOOP,
"__builtin_maybe_infinite_loop",
+ void_ftype, "__builtin_maybe_infinite_loop", 0);
+ /* APPLE LOCAL end lno */
t = tree_cons (NULL_TREE, boolean_type_node, end_params_node);
t = tree_cons (NULL_TREE, boolean_type_node, t);
--- ./java/decl.c.~1~ 2007-02-02 11:13:32.000000000 -0800
+++ ./java/decl.c 2007-04-21 15:54:05.000000000 -0700
@@ -573,6 +573,8 @@ java_init_decl_processing (void)
/* Define these next since types below may used them. */
integer_type_node = java_type_for_size (INT_TYPE_SIZE, 0);
+ /* APPLE LOCAL lno */
+ long_integer_type_node = java_type_for_size (LONG_TYPE_SIZE, 0);
integer_zero_node = build_int_cst (NULL_TREE, 0);
integer_one_node = build_int_cst (NULL_TREE, 1);
integer_two_node = build_int_cst (NULL_TREE, 2);
--- ./loop-doloop.c.~1~ 2006-12-14 15:12:40.000000000 -0800
+++ ./loop-doloop.c 2007-04-21 15:54:05.000000000 -0700
@@ -174,6 +174,13 @@ doloop_valid_p (struct loop *loop, struc
If the absolute increment is not 1, the loop can be infinite
even with LTU/GTU, e.g. for (i = 3; i > 0; i -= 2)
+ APPLE LOCAL begin lno
+ Note that with LE and GE, the loop behavior is undefined
+ (C++ standard section 5 clause 5) if an overflow occurs, say
+ between INT_MAX and INT_MAX + 1. We thus don't have to worry
+ about these two cases.
+ APPLE LOCAL end lno
+
??? We could compute these conditions at run-time and have a
additional jump around the loop to ensure an infinite loop.
However, it is very unlikely that this is the intended
--- ./opts.c.~1~ 2007-04-21 15:48:09.000000000 -0700
+++ ./opts.c 2007-04-21 15:54:05.000000000 -0700
@@ -708,6 +708,13 @@ decode_options (unsigned int argc, const
flag_tree_dce = 1;
flag_tree_dom = 1;
flag_tree_dse = 1;
+ /* APPLE LOCAL begin lno */
+ flag_tree_loop_im = 1;
+ flag_ivopts = 1;
+ flag_tree_vectorize = 0;
+ flag_tree_loop_linear = 0;
+ flag_tree_pre = 1;
+ /* APPLE LOCAL end lno */
flag_tree_ter = 1;
flag_tree_sra = 1;
flag_tree_copyrename = 1;
--- ./passes.c.~1~ 2007-04-21 15:48:10.000000000 -0700
+++ ./passes.c 2007-04-21 15:57:55.000000000 -0700
@@ -594,6 +594,9 @@ init_optimization_passes (void)
NEXT_PASS (pass_check_data_deps);
NEXT_PASS (pass_linear_transform);
NEXT_PASS (pass_iv_canon);
+ /* APPLE LOCAL begin lno */
+ NEXT_PASS (pass_mark_maybe_inf_loops);
+ /* APPLE LOCAL end lno */
NEXT_PASS (pass_if_conversion);
NEXT_PASS (pass_vectorize);
{
--- ./testsuite/lib/scantree.exp.~1~ 2006-11-16 23:21:25.000000000 -0800
+++ ./testsuite/lib/scantree.exp 2007-04-21 15:54:05.000000000 -0700
@@ -17,6 +17,54 @@
# Various utilities for scanning tree dump output, used by gcc-dg.exp and
# g++-dg.exp.
+# APPLE LOCAL begin lno
+# Utility for diffing compiler result against an expected output file.
+# Invoked via dg-final. Call pass if there are no differences between
+# the output of the compiler and the expected output file, otherwise
+# fail. The expected output file has the same name as the output
+# file, and is stored in the same directory as the testcase.
+#
+# Argument 0 is the suffix for the tree dump file
+# Argument 1 handles expected failures and the like
+proc diff-tree-dumps { args } {
+ if { [llength $args] < 1 } {
+ error "diff-tree-dumps: too few arguments"
+ return
+ }
+ if { [llength $args] > 2 } {
+ error "diff-tree-dumps:: too many arguments"
+ return
+ }
+ if { [llength $args] >= 2 } {
+ switch [dg-process-target [lindex $args 1]] {
+ "S" { }
+ "N" { return }
+ "F" { setup_xfail "*-*-*" }
+ "P" { }
+ }
+ }
+
+ # This assumes that we are two frames down from dg-test, and that
+ # it still stores the filename of the testcase in a local variable "name".
+ # A cleaner solution would require a new dejagnu release.
+ upvar 2 prog testcase
+
+ # This must match the rule in gcc-dg.exp.
+ # APPLE LOCAL Selective inlining of functions that use Altivec 3837835
+ set new_file "[glob [file tail $testcase].\[ti\]??.[lindex $args 0]]"
+ set reference_file "[glob $testcase.[lindex $args 0]]"
+
+ set test_result [diff $reference_file $new_file]
+
+ if { $test_result == 1 } {
+ pass "$testcase diff-tree-dumps [lindex $args 0]"
+ } else {
+ fail "$testcase diff-tree-dumps [lindex $args 0]"
+ local_exec (diff $reference_file $new_file 0);
+ }
+}
+# APPLE LOCAL end lno
+
load_lib scandump.exp
# Utility for scanning compiler result, invoked via dg-final.
--- ./timevar.def.~1~ 2007-03-12 19:03:09.000000000 -0700
+++ ./timevar.def 2007-04-21 15:54:05.000000000 -0700
@@ -102,6 +102,8 @@ DEFTIMEVAR (TV_TREE_DSE , "tree DS
DEFTIMEVAR (TV_TREE_MERGE_PHI , "PHI merge")
DEFTIMEVAR (TV_TREE_LOOP , "tree loop optimization")
DEFTIMEVAR (TV_TREE_LOOP_BOUNDS , "tree loop bounds")
+/* APPLE LOCAL lno */
+DEFTIMEVAR (TV_MARK_MILOOPS , "mark maybe infinite loops")
DEFTIMEVAR (TV_LIM , "loop invariant motion")
DEFTIMEVAR (TV_TREE_LOOP_IVCANON , "tree canonical iv")
DEFTIMEVAR (TV_SCEV_CONST , "scev constant prop")
--- ./tree-cfg.c.~1~ 2007-04-13 10:06:21.000000000 -0700
+++ ./tree-cfg.c 2007-04-21 15:54:05.000000000 -0700
@@ -4081,7 +4081,8 @@ tree_redirect_edge_and_branch (edge e, b
return ret;
if (e->dest == dest)
- return NULL;
+ /* APPLE LOCAL lno */
+ return e;
label = tree_block_label (dest);
--- ./tree-flow.h.~1~ 2007-04-13 10:06:20.000000000 -0700
+++ ./tree-flow.h 2007-04-21 15:54:05.000000000 -0700
@@ -1032,6 +1032,11 @@ enum move_pos
};
extern enum move_pos movement_possibility (tree);
+/* APPLE LOCAL begin lno */
+/* In tree-ssa-loop*.c */
+void mark_maybe_infinite_loops (struct loops *);
+/* APPLE LOCAL end lno */
+
/* The reasons a variable may escape a function. */
enum escape_type
{
--- ./tree-pass.h.~1~ 2007-04-21 15:48:08.000000000 -0700
+++ ./tree-pass.h 2007-04-21 15:54:05.000000000 -0700
@@ -244,6 +244,9 @@ extern struct tree_opt_pass pass_tree_lo
extern struct tree_opt_pass pass_tree_loop_init;
extern struct tree_opt_pass pass_lim;
extern struct tree_opt_pass pass_tree_unswitch;
+/* APPLE LOCAL begin lno */
+extern struct tree_opt_pass pass_mark_maybe_inf_loops;
+/* APPLE LOCAL end lno */
extern struct tree_opt_pass pass_iv_canon;
extern struct tree_opt_pass pass_scev_cprop;
extern struct tree_opt_pass pass_empty_loop;
--- ./tree-ssa-loop-niter.c.~1~ 2007-04-21 15:48:08.000000000 -0700
+++ ./tree-ssa-loop-niter.c 2007-04-21 15:54:05.000000000 -0700
@@ -3137,3 +3137,87 @@ substitute_in_loop_info (struct loop *lo
{
loop->nb_iterations = simplify_replace_tree (loop->nb_iterations, name, val);
}
+
+/* APPLE LOCAL begin lno */
+/*
+
+ Removal of loops in DCE.
+
+*/
+
+/* If we are able to prove that the LOOP always exits, turn off the
+ EDGE_DFS_BACK flag from its latch edge. */
+
+static void
+unmark_surely_finite_loop (struct loop *loop)
+{
+ edge *exits;
+ unsigned i, n_exits;
+ struct tree_niter_desc niter_desc;
+
+ exits = get_loop_exit_edges (loop, &n_exits);
+ for (i = 0; i < n_exits; i++)
+ if (number_of_iterations_exit (loop, exits[i], &niter_desc, false))
+ {
+ loop_latch_edge (loop)->flags &= ~EDGE_DFS_BACK;
+ return;
+ }
+}
+
+/* Emit special statements preventing removal of possibly infinite loops in
+ CD_DCE to the latches of LOOPS for that we are not able to prove that they
+ iterate just finite number of times. */
+
+void
+mark_maybe_infinite_loops (struct loops *loops)
+{
+ unsigned i;
+ struct loop *loop;
+ basic_block bb;
+ edge e;
+ tree stmt;
+ bool inserted = false;
+ block_stmt_iterator bsi;
+
+ mark_dfs_back_edges ();
+
+ for (i = 1; i < loops->num; i++)
+ {
+ loop = loops->parray[i];
+ if (loop)
+ unmark_surely_finite_loop (loop);
+ }
+
+ FOR_EACH_BB (bb)
+ {
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->flags & EDGE_DFS_BACK)
+ {
+ stmt = build_function_call_expr
(built_in_decls[BUILT_IN_MAYBE_INFINITE_LOOP],
+ NULL);
+
+ mark_new_vars_to_rename (stmt);
+
+ if (!(e->flags & EDGE_ABNORMAL))
+ {
+ bsi_insert_on_edge (e, stmt);
+ inserted = true;
+ continue;
+ }
+
+ /* We cannot insert on abnormal edge, so insert to the basic block
+ at its start. */
+ bsi = bsi_last (e->src);
+ if (!bsi_end_p (bsi)
+ && stmt_ends_bb_p (bsi_stmt (bsi)))
+ bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
+ else
+ bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
+ }
+ }
+
+ if (inserted)
+ loop_commit_inserts ();
+}
+/* APPLE LOCAL end lno */
--- ./tree-ssa-loop.c.~1~ 2007-03-12 19:03:09.000000000 -0700
+++ ./tree-ssa-loop.c 2007-04-21 15:55:56.000000000 -0700
@@ -532,3 +532,42 @@ struct tree_opt_pass pass_tree_loop_done
TODO_cleanup_cfg | TODO_dump_func, /* todo_flags_finish */
0 /* letter */
};
+
+/* APPLE LOCAL begin lno */
+/* Marks loops that cannot be removed in DCE, since they are possibly
+ infinite. */
+
+static unsigned int
+tree_mark_maybe_inf_loops (void)
+{
+ if (!current_loops)
+ return 0;
+
+ mark_maybe_infinite_loops (current_loops);
+ return 0;
+}
+
+static bool
+gate_tree_mark_maybe_inf_loops (void)
+{
+ return (flag_tree_dce != 0 && optimize >= 2);
+}
+
+struct tree_opt_pass pass_mark_maybe_inf_loops =
+{
+ "miloops", /* name */
+ gate_tree_mark_maybe_inf_loops, /* gate */
+ tree_mark_maybe_inf_loops, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_MARK_MILOOPS, /* tv_id */
+ PROP_cfg | PROP_ssa, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_update_ssa | TODO_dump_func, /* todo_flags_finish */
+ 0
+};
+
+/* APPLE LOCAL end lno */
--------------