This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] Loop analysis
- From: Pop Sébastian <pop at gauvain dot u-strasbg dot fr>
- To: dnovillo at redhat dot com, jh at suse dot cz, gcc-patches at gcc dot gnu dot org
- Date: Tue, 15 Apr 2003 15:56:16 +0200
- Subject: [tree-ssa] Loop analysis
Hi,
This patch allows the tree-ssa-branch to reuse the loop detection pass.
For the moment it only initializes the loops structure.
I don't know whether it is worth to handle differences between representations
in a cfg_hook structure, or simply guard the code with a boolean: cfg_at_rtl_level.
What is difficult is to register static functions in the hook structure.
I think that the guarded code is the better solution.
Bootstrapped on i686.
2003-04-15 Sebastian Pop <s dot pop at laposte dot net>
* cfghooks.h, cfghooks.c: New files.
* Makefile.in (BASIC_BLOCK_H): Depends on cfghooks.h.
(OBJS): Add cfghooks.o.
(tree-optimize.o): Depends on cfgloop.h.
(cfghooks.o): New rule.
* basic-block.h (split_edge): Rename to rtl_split_edge.
(tree_split_edge): Declare.
(create_bb): Declare extern here.
(verify_flow_info): Rename to rtl_verify_flow_info.
(tree_verify_flow_info): Declare.
(cfghooks.h): Included here.
* cfgloop.c (tree.h, tree-flow.h): Included.
(make_forwarder_block): Renamed to rtl_make_forwarder_block.
(tree_make_forwarder_block): New static function.
(blocks_headers): Declared static.
(HEADER_BLOCK): Use blocks_headers instead of bb's .aux field.
(redirect_edge_with_latch_update, make_forwarder_block,
canonicalize_loop_headers): Don't allocate .aux, but makes grow
the blocks_headers array.
(canonicalize_loop_headers): Initialize/free the blocks_headers
array rather than the bb's .aux field.
(canonicalize_loop_headers, ): Call rtl_make_forwarder_block or
tree_make_forwarder_block following the value of cfg_at_rtl_level.
* cfgloopmanip.c (loop_split_edge_with_NULL): New static function.
(remove_path, force_single_succ_latches):
Call loop_split_edge_with_NULL instead of loop_split_edge_with.
* cfgrtl.c (split_block): Update the comment.
(split_edge): Renamed rtl_split_edge.
(verify_flow_info): Renamed rtl_verify_flow_info.
* loop-init.c (loop_optimizer_init, loop_optimizer_finalize):
Guard code with cfg_at_rtl_level.
* toplev.c (rest_of_compilation): Call rtl_register_cfg_hooks.
* tree-cfg.c (create_bb): Declared extern.
(build_tree_cfg): Call tree_register_cfg_hooks.
(make_edges, make_exit_edges): Remove the use of EDGE_FALLTHRU.
(bsi_commit_first_edge_insert): Use split_edge.
(tree_split_edge, tree_verify_flow_info): New functions.
* tree-optimize.c (cfgloop.h): Included.
(optimize_function_tree): Call loop_optimizer_init and
loop_optimizer_finalize.
Index: Makefile.in
===================================================================
RCS file: /home/pop/cvsroot/gcc-cvs/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.83
diff -u -3 -p -d -u -p -r1.903.2.83 Makefile.in
--- Makefile.in 9 Apr 2003 19:27:15 -0000 1.903.2.83
+++ Makefile.in 15 Apr 2003 10:41:19 -0000
@@ -660,7 +660,7 @@ PARAMS_H = params.h params.def
TREE_H = tree.h tree.def $(MACHMODE_H) tree-check.h version.h builtins.def \
location.h
BASIC_BLOCK_H = basic-block.h bitmap.h sbitmap.h varray.h $(PARTITION_H) \
- hard-reg-set.h
+ hard-reg-set.h cfghooks.h
DEMANGLE_H = $(srcdir)/../include/demangle.h
RECOG_H = recog.h
EXPR_H = expr.h
@@ -854,7 +854,7 @@ OBJS = tree-cfg.o tree-dfa.o tree-ssa.o
sibcall.o simplify-rtx.o sreal.o ssa.o ssa-ccp.o ssa-dce.o stmt.o \
stor-layout.o stringpool.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
tree-inline.o unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o \
- alloc-pool.o et-forest.o cgraph.o cgraphunit.o \
+ alloc-pool.o et-forest.o cgraph.o cgraphunit.o cfghooks.o \
$(GGC) $(out_object_file) $(EXTRA_OBJS) $(host_hook_obj)
BACKEND = main.o libbackend.a
@@ -1532,7 +1532,7 @@ tree-dfa.o : tree-dfa.c $(TREE_FLOW_H) $
tree-optimize.o : tree-optimize.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) \
$(GGC_H) output.h diagnostic.h ssa.h errors.h flags.h tree-alias-common.h \
- $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H)
+ $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) cfgloop.h
c-simplify.o : c-simplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
$(C_TREE_H) $(C_COMMON_H) diagnostic.h $(TREE_SIMPLE_H) varray.h flags.h \
langhooks.h toplev.h rtl.h $(TREE_FLOW_H) langhooks-def.h \
@@ -1747,6 +1747,8 @@ flow.o : flow.c $(CONFIG_H) $(SYSTEM_H)
cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h insn-config.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
function.h except.h $(GGC_H) $(TM_P_H) alloc-pool.h
+cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
+ $(BASIC_BLOCK_H) tree-flow.h cfglayout.h
cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
function.h except.h $(GGC_H) $(TM_P_H) insn-config.h
Index: basic-block.h
===================================================================
RCS file: /home/pop/cvsroot/gcc-cvs/gcc/gcc/basic-block.h,v
retrieving revision 1.153.2.21
diff -u -3 -p -d -u -p -r1.153.2.21 basic-block.h
--- basic-block.h 9 Apr 2003 19:27:16 -0000 1.153.2.21
+++ basic-block.h 15 Apr 2003 12:35:47 -0000
@@ -345,7 +345,8 @@ extern void update_bb_for_insn PARAMS (
extern void free_basic_block_vars PARAMS ((int));
extern edge split_block PARAMS ((basic_block, rtx));
-extern basic_block split_edge PARAMS ((edge));
+extern basic_block rtl_split_edge PARAMS ((edge));
+extern basic_block tree_split_edge PARAMS ((edge));
extern void insert_insn_on_edge PARAMS ((rtx, edge));
extern void commit_edge_insertions PARAMS ((void));
@@ -386,6 +387,7 @@ extern void dump_edge_info PARAMS ((FIL
extern void clear_edges PARAMS ((void));
extern void mark_critical_edges PARAMS ((void));
extern rtx first_insn_after_basic_block_note PARAMS ((basic_block));
+extern basic_block create_bb PARAMS ((void));
/* Dominator information for basic blocks. */
@@ -593,7 +595,8 @@ extern void free_aux_for_edges PARAMS (
/* This function is always defined so it can be called from the
debugger, and it is declared extern so we don't get warnings about
it being unused. */
-extern void verify_flow_info PARAMS ((void));
+extern void rtl_verify_flow_info PARAMS ((void));
+extern void tree_verify_flow_info PARAMS ((void));
typedef struct conflict_graph_def *conflict_graph;
@@ -656,4 +659,7 @@ extern void redirect_immediate_dominator
basic_block));
void iterate_fix_dominators PARAMS ((dominance_info, basic_block *, int));
extern void verify_dominators PARAMS ((dominance_info));
+
+#include "cfghooks.h"
+
#endif /* GCC_BASIC_BLOCK_H */
Index: cfghooks.c
===================================================================
RCS file: cfghooks.c
diff -N cfghooks.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ cfghooks.c 15 Apr 2003 12:38:53 -0000
@@ -0,0 +1,62 @@
+/* Hooks for cfg representation specific functions.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ Contributed by Sebastian Pop <s dot pop at laposte dot net>
+
+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 later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or 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. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "basic-block.h"
+#include "tree-flow.h"
+
+
+/* Containers. */
+struct cfg_hooks tree_cfg_hooks = {
+ tree_split_edge,
+ tree_verify_flow_info
+};
+
+struct cfg_hooks rtl_cfg_hooks = {
+ rtl_split_edge,
+ rtl_verify_flow_info
+};
+
+/* A pointer to one of the hooks containers. */
+struct cfg_hooks *cfg_hooks;
+bool cfg_at_rtl_level;
+
+/* Initialization of functions specific to the tree IR. */
+void
+tree_register_cfg_hooks ()
+{
+ cfg_at_rtl_level = false;
+ cfg_hooks = &tree_cfg_hooks;
+}
+
+/* Initialization of functions specific to the rtl IR. */
+void
+rtl_register_cfg_hooks ()
+{
+ cfg_at_rtl_level = true;
+ cfg_hooks = &rtl_cfg_hooks;
+}
+
Index: cfghooks.h
===================================================================
RCS file: cfghooks.h
diff -N cfghooks.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ cfghooks.h 15 Apr 2003 11:49:51 -0000
@@ -0,0 +1,46 @@
+/* Hooks for cfg representation specific functions.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ Contributed by Sebastian Pop <s dot pop at laposte dot net>
+
+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 later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or 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. */
+
+#ifndef GCC_CFGHOOKS_H
+#define GCC_CFGHOOKS_H
+
+struct cfg_hooks
+{
+ basic_block (*cfgh_split_edge) PARAMS ((edge));
+ void (*cfgh_verify_flow_info) PARAMS ((void));
+};
+
+#define split_edge(e) cfg_hooks->cfgh_split_edge (e)
+#define verify_flow_info() cfg_hooks->cfgh_verify_flow_info ()
+
+/* Hooks containers. */
+extern struct cfg_hooks tree_cfg_hooks;
+extern struct cfg_hooks rtl_cfg_hooks;
+
+/* A pointer to one of the hooks containers. */
+extern struct cfg_hooks *cfg_hooks;
+extern bool cfg_at_rtl_level;
+
+/* Declarations. */
+extern void tree_register_cfg_hooks PARAMS ((void));
+extern void rtl_register_cfg_hooks PARAMS ((void));
+
+#endif /* GCC_CFGHOOKS_H */
Index: cfgloop.c
===================================================================
RCS file: /home/pop/cvsroot/gcc-cvs/gcc/gcc/cfgloop.c,v
retrieving revision 1.14.2.8
diff -u -3 -p -d -u -p -r1.14.2.8 cfgloop.c
--- cfgloop.c 9 Apr 2003 19:27:21 -0000 1.14.2.8
+++ cfgloop.c 15 Apr 2003 12:05:39 -0000
@@ -29,6 +29,9 @@ Software Foundation, 59 Temple Place - S
#include "cfgloop.h"
#include "flags.h"
+#include "tree.h"
+#include "tree-flow.h"
+
/* Ratio of frequencies of edges so that one of more latch edges is
considered to belong to inner loop with same header. */
#define HEAVY_EDGE_RATIO 8
@@ -44,8 +47,10 @@ static basic_block flow_loop_pre_header_
static int flow_loop_level_compute PARAMS ((struct loop *));
static int flow_loops_level_compute PARAMS ((struct loops *));
static void establish_preds PARAMS ((struct loop *));
-static basic_block make_forwarder_block PARAMS ((basic_block, int, int,
- edge, int));
+static basic_block rtl_make_forwarder_block PARAMS ((basic_block, int, int,
+ edge, int));
+static basic_block tree_make_forwarder_block PARAMS ((basic_block, int, int,
+ edge, int));
static void canonicalize_loop_headers PARAMS ((void));
static bool glb_enum_p PARAMS ((basic_block, void *));
static void redirect_edge_with_latch_update PARAMS ((edge, basic_block));
@@ -583,7 +588,8 @@ flow_loop_scan (loops, loop, flags)
return 1;
}
-#define HEADER_BLOCK(B) (* (int *) (B)->aux)
+static varray_type blocks_headers;
+#define HEADER_BLOCK(B) (VARRAY_INT (blocks_headers, B->index))
#define LATCH_EDGE(E) (*(int *) (E)->aux)
/* Redirect edge and update latch and header info. */
@@ -597,7 +603,7 @@ redirect_edge_with_latch_update (e, to)
jump = redirect_edge_and_branch_force (e, to);
if (jump)
{
- alloc_aux_for_block (jump, sizeof (int));
+ VARRAY_GROW (blocks_headers, last_basic_block);
HEADER_BLOCK (jump) = 0;
alloc_aux_for_edge (jump->pred, sizeof (int));
LATCH_EDGE (jump->succ) = LATCH_EDGE (e);
@@ -612,7 +618,7 @@ redirect_edge_with_latch_update (e, to)
part. */
static basic_block
-make_forwarder_block (bb, redirect_latch, redirect_nonlatch, except,
+rtl_make_forwarder_block (bb, redirect_latch, redirect_nonlatch, except,
conn_latch)
basic_block bb;
int redirect_latch;
@@ -634,7 +640,7 @@ make_forwarder_block (bb, redirect_latch
dummy = fallthru->src;
bb = fallthru->dest;
- bb->aux = xmalloc (sizeof (int));
+ VARRAY_GROW (blocks_headers, last_basic_block);
HEADER_BLOCK (dummy) = 0;
HEADER_BLOCK (bb) = 1;
@@ -662,6 +668,64 @@ make_forwarder_block (bb, redirect_latch
return dummy;
}
+static basic_block
+tree_make_forwarder_block (bb, redirect_latch, redirect_nonlatch, except,
+ conn_latch)
+ basic_block bb;
+ int redirect_latch;
+ int redirect_nonlatch;
+ edge except;
+ int conn_latch;
+{
+ edge e, next_e, fallthru;
+ basic_block dummy;
+
+ /* Create the new basic block. */
+ dummy = create_bb ();
+ alloc_aux_for_block (dummy, sizeof (struct bb_ann_d));
+ dummy->count = bb->count;
+ dummy->frequency = bb->frequency;
+ dummy->loop_depth = bb->loop_depth;
+ dummy->head_tree_p = NULL;
+ dummy->end_tree_p = NULL;
+
+ /* Redirect the incoming edges. */
+ dummy->pred = bb->pred;
+ bb->pred = NULL;
+ for (e = dummy->pred; e; e = e->pred_next)
+ e->dest = dummy;
+
+ fallthru = make_edge (dummy, bb, 0);
+
+ VARRAY_GROW (blocks_headers, last_basic_block);
+ HEADER_BLOCK (dummy) = 0;
+ HEADER_BLOCK (bb) = 1;
+
+ /* Redirect back edges we want to keep. */
+ for (e = dummy->pred; e; e = next_e)
+ {
+ next_e = e->pred_next;
+ if (e == except
+ || !((redirect_latch && LATCH_EDGE (e))
+ || (redirect_nonlatch && !LATCH_EDGE (e))))
+ {
+ dummy->frequency -= EDGE_FREQUENCY (e);
+ dummy->count -= e->count;
+ if (dummy->frequency < 0)
+ dummy->frequency = 0;
+ if (dummy->count < 0)
+ dummy->count = 0;
+ redirect_edge_succ (e, bb);
+ }
+ }
+
+ alloc_aux_for_edge (fallthru, sizeof (int));
+ LATCH_EDGE (fallthru) = conn_latch;
+
+ return dummy;
+}
+
+
/* Takes care of merging natural loops with shared headers. */
static void
canonicalize_loop_headers ()
@@ -673,7 +737,7 @@ canonicalize_loop_headers ()
/* Compute the dominators. */
dom = calculate_dominance_info (CDI_DOMINATORS);
- alloc_aux_for_blocks (sizeof (int));
+ VARRAY_INT_INIT (blocks_headers, last_basic_block, "blocks_headers");
alloc_aux_for_edges (sizeof (int));
/* Split blocks so that each loop has only single latch. */
@@ -712,7 +776,7 @@ canonicalize_loop_headers ()
alloc_aux_for_edge (bb->succ, sizeof (int));
LATCH_EDGE (bb->succ) = 0;
- alloc_aux_for_block (bb, sizeof (int));
+ VARRAY_GROW (blocks_headers, last_basic_block);
HEADER_BLOCK (bb) = 0;
}
@@ -754,18 +818,33 @@ canonicalize_loop_headers ()
heavy = e;
}
- if (is_heavy)
+ if (cfg_at_rtl_level)
{
- basic_block new_header =
- make_forwarder_block (header, true, true, heavy, 0);
- if (num_latch > 2)
- make_forwarder_block (new_header, true, false, NULL, 1);
+ if (is_heavy)
+ {
+ basic_block new_header =
+ rtl_make_forwarder_block (header, true, true, heavy, 0);
+ if (num_latch > 2)
+ rtl_make_forwarder_block (new_header, true, false, NULL, 1);
+ }
+ else
+ rtl_make_forwarder_block (header, true, false, NULL, 1);
}
else
- make_forwarder_block (header, true, false, NULL, 1);
+ {
+ if (is_heavy)
+ {
+ basic_block new_header =
+ tree_make_forwarder_block (header, true, true, heavy, 0);
+ if (num_latch > 2)
+ tree_make_forwarder_block (new_header, true, false, NULL, 1);
+ }
+ else
+ tree_make_forwarder_block (header, true, false, NULL, 1);
+ }
}
- free_aux_for_blocks ();
+ VARRAY_CLEAR (blocks_headers);
free_aux_for_edges ();
free_dominance_info (dom);
}
Index: cfgloopmanip.c
===================================================================
RCS file: /home/pop/cvsroot/gcc-cvs/gcc/gcc/cfgloopmanip.c,v
retrieving revision 1.3.2.3
diff -u -3 -p -d -u -p -r1.3.2.3 cfgloopmanip.c
--- cfgloopmanip.c 9 Apr 2003 19:27:21 -0000 1.3.2.3
+++ cfgloopmanip.c 15 Apr 2003 12:17:24 -0000
@@ -59,6 +59,8 @@ static void record_exit_edges PARAMS ((
static basic_block create_preheader PARAMS ((struct loop *, dominance_info,
int));
static void fix_irreducible_loops PARAMS ((basic_block));
+static basic_block loop_split_edge_with_NULL PARAMS ((edge, struct loops *));
+
/* Splits basic block BB after INSN, returns created edge. Updates loops
and dominators. */
@@ -380,7 +382,7 @@ remove_path (loops, e)
fix -- when e->dest has exactly one predecessor, this corresponds
to blocks dominated by e->dest, if not, split the edge. */
if (e->dest->pred->pred_next)
- e = loop_split_edge_with (e, NULL_RTX, loops)->pred;
+ e = loop_split_edge_with_NULL (e, loops)->pred;
/* It may happen that by removing path we remove one or more loops
we belong to. In this case first unloop the loops, then proceed
@@ -1482,7 +1484,7 @@ force_single_succ_latches (loops)
for (e = loop->header->pred; e->src != loop->latch; e = e->pred_next)
continue;
- loop_split_edge_with (e, NULL_RTX, loops);
+ loop_split_edge_with_NULL (e, loops);
}
loops->state |= LOOPS_HAVE_SIMPLE_LATCHES;
}
@@ -1545,3 +1547,61 @@ loop_split_edge_with (e, insns, loops)
return new_bb;
}
+
+/* Same function as "loop_split_edge_with (e, NULL, loops)",
+ independent of the tree/rtl representation. */
+
+static basic_block
+loop_split_edge_with_NULL (e, loops)
+ edge e;
+ struct loops *loops;
+{
+ basic_block src, dest, new_bb;
+ struct loop *loop_c;
+ edge new_e;
+
+ src = e->src;
+ dest = e->dest;
+
+ loop_c = find_common_loop (src->loop_father, dest->loop_father);
+
+ /* Create basic block for it. */
+
+ if (cfg_at_rtl_level)
+ new_bb = create_basic_block (NULL_RTX, NULL_RTX, EXIT_BLOCK_PTR->prev_bb);
+ else
+ new_bb = create_bb ();
+
+ add_to_dominance_info (loops->cfg.dom, new_bb);
+ add_bb_to_loop (new_bb, loop_c);
+ new_bb->flags = 0;
+
+ new_e = make_edge (new_bb, dest, cfg_at_rtl_level ? EDGE_FALLTHRU : 0);
+ new_e->probability = REG_BR_PROB_BASE;
+ new_e->count = e->count;
+ if (e->flags & EDGE_IRREDUCIBLE_LOOP)
+ {
+ new_bb->flags |= BB_IRREDUCIBLE_LOOP;
+ new_e->flags |= EDGE_IRREDUCIBLE_LOOP;
+ }
+
+ new_bb->count = e->count;
+ new_bb->frequency = EDGE_FREQUENCY (e);
+
+ if (cfg_at_rtl_level)
+ cfg_layout_redirect_edge (e, new_bb);
+ else
+ redirect_edge_succ (e, new_bb);
+
+ alloc_aux_for_block (new_bb, sizeof (struct reorder_block_def));
+
+ set_immediate_dominator (loops->cfg.dom, new_bb, src);
+ set_immediate_dominator (loops->cfg.dom, dest,
+ recount_dominator (loops->cfg.dom, dest));
+
+ if (dest->loop_father->latch == src)
+ dest->loop_father->latch = new_bb;
+
+ return new_bb;
+}
+
Index: cfgrtl.c
===================================================================
RCS file: /home/pop/cvsroot/gcc-cvs/gcc/gcc/cfgrtl.c,v
retrieving revision 1.57.2.8
diff -u -3 -p -d -u -p -r1.57.2.8 cfgrtl.c
--- cfgrtl.c 9 Apr 2003 19:27:21 -0000 1.57.2.8
+++ cfgrtl.c 15 Apr 2003 11:37:32 -0000
@@ -470,9 +470,7 @@ update_bb_for_insn (bb)
}
/* Split a block BB after insn INSN creating a new fallthru edge.
- Return the new edge. Note that to keep other parts of the compiler happy,
- this function renumbers all the basic blocks so that the new
- one has a number one greater than the block split. */
+ Return the new edge. */
edge
split_block (bb, insn)
@@ -1227,7 +1225,7 @@ back_edge_of_syntactic_loop_p (bb1, bb2)
block with multiple predecessors is not handled optimally. */
basic_block
-split_edge (edge_in)
+rtl_split_edge (edge_in)
edge edge_in;
{
basic_block bb;
@@ -1738,7 +1736,7 @@ update_br_prob_note (bb)
(reachability of basic blocks, life information, etc. etc.). */
void
-verify_flow_info ()
+rtl_verify_flow_info ()
{
const int max_uid = get_max_uid ();
const rtx rtx_first = get_insns ();
Index: loop-init.c
===================================================================
RCS file: /home/pop/cvsroot/gcc-cvs/gcc/gcc/loop-init.c,v
retrieving revision 1.2.2.1
diff -u -3 -p -d -u -p -r1.2.2.1 loop-init.c
--- loop-init.c 9 Feb 2003 21:21:39 -0000 1.2.2.1
+++ loop-init.c 15 Apr 2003 11:52:54 -0000
@@ -41,9 +41,10 @@ loop_optimizer_init (dumpfile)
/* Avoid annoying special cases of edges going to exit
block. */
- for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
- if ((e->flags & EDGE_FALLTHRU) && e->src->succ->succ_next)
- split_edge (e);
+ if (cfg_at_rtl_level)
+ for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
+ if ((e->flags & EDGE_FALLTHRU) && e->src->succ->succ_next)
+ split_edge (e);
/* Find the loops. */
@@ -61,11 +62,14 @@ loop_optimizer_init (dumpfile)
free (loops->cfg.dfs_order);
loops->cfg.dfs_order = NULL;
- /* Initialize structures for layout changes. */
- cfg_layout_initialize (loops);
-
- /* Create pre-headers. */
- create_preheaders (loops, CP_SIMPLE_PREHEADERS | CP_INSIDE_CFGLAYOUT);
+ if (cfg_at_rtl_level)
+ {
+ /* Initialize structures for layout changes. */
+ cfg_layout_initialize (loops);
+
+ /* Create pre-headers. */
+ create_preheaders (loops, CP_SIMPLE_PREHEADERS | CP_INSIDE_CFGLAYOUT);
+ }
/* Force all latches to have only single successor. */
force_single_succ_latches (loops);
@@ -94,19 +98,24 @@ loop_optimizer_finalize (loops, dumpfile
/* Finalize layout changes. */
/* Make chain. */
- FOR_EACH_BB (bb)
- if (bb->next_bb != EXIT_BLOCK_PTR)
- RBI (bb)->next = bb->next_bb;
-
- /* Another dump. */
- flow_loops_dump (loops, dumpfile, NULL, 1);
+ if (cfg_at_rtl_level)
+ FOR_EACH_BB (bb)
+ if (bb->next_bb != EXIT_BLOCK_PTR)
+ RBI (bb)->next = bb->next_bb;
- /* Clean up. */
- flow_loops_free (loops);
- free (loops);
+ if (loops)
+ {
+ /* Another dump. */
+ flow_loops_dump (loops, dumpfile, NULL, 1);
+
+ /* Clean up. */
+ flow_loops_free (loops);
+ free (loops);
+ }
/* Finalize changes. */
- cfg_layout_finalize ();
+ if (cfg_at_rtl_level)
+ cfg_layout_finalize ();
/* Checking. */
#ifdef ENABLE_CHECKING
Index: toplev.c
===================================================================
RCS file: /home/pop/cvsroot/gcc-cvs/gcc/gcc/toplev.c,v
retrieving revision 1.654.2.48
diff -u -3 -p -d -u -p -r1.654.2.48 toplev.c
--- toplev.c 9 Apr 2003 19:27:39 -0000 1.654.2.48
+++ toplev.c 11 Apr 2003 12:06:09 -0000
@@ -2471,6 +2471,9 @@ rest_of_compilation (decl)
timevar_push (TV_REST_OF_COMPILATION);
+ /* Register specific tree functions. */
+ rtl_register_cfg_hooks ();
+
/* Now that we're out of the frontend, we shouldn't have any more
CONCATs anywhere. */
generating_concat_p = 0;
Index: tree-cfg.c
===================================================================
RCS file: /home/pop/cvsroot/gcc-cvs/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.71
diff -u -3 -p -d -u -p -r1.1.4.71 tree-cfg.c
--- tree-cfg.c 9 Apr 2003 19:27:40 -0000 1.1.4.71
+++ tree-cfg.c 15 Apr 2003 12:27:21 -0000
@@ -1,5 +1,5 @@
/* Control flow functions for trees.
- Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo at redhat dot com>
This file is part of GCC.
@@ -77,7 +77,6 @@ static basic_block make_bind_expr_blocks
static inline void add_stmt_to_bb PARAMS ((tree *, basic_block, tree));
static inline void append_stmt_to_bb PARAMS ((tree *, basic_block, tree));
static inline void set_parent_stmt PARAMS ((tree *, tree));
-static basic_block create_bb PARAMS ((void));
/* Edges. */
static void make_edges PARAMS ((void));
@@ -176,6 +175,9 @@ build_tree_cfg (fnbody)
timevar_push (TV_TREE_CFG);
+ /* Register specific tree functions. */
+ tree_register_cfg_hooks ();
+
/* Initialize the basic block array. */
n_basic_blocks = 0;
last_basic_block = 0;
@@ -613,7 +615,7 @@ append_stmt_to_bb (stmt_p, bb, parent)
/* Create and return a new basic block. */
-static basic_block
+basic_block
create_bb ()
{
basic_block bb;
@@ -656,7 +658,7 @@ make_edges ()
/* Create an edge from entry to the first block with executable
statements in it. */
- make_edge (ENTRY_BLOCK_PTR, BASIC_BLOCK (0), EDGE_FALLTHRU);
+ make_edge (ENTRY_BLOCK_PTR, BASIC_BLOCK (0), 0);
/* Traverse basic block array placing edges. */
FOR_EACH_BB (bb)
@@ -684,7 +686,7 @@ make_edges ()
/* Finally, if no edges were created above, this is a regular
basic block that only needs a fallthru edge. */
if (bb->succ == NULL)
- make_edge (bb, successor_block (bb), EDGE_FALLTHRU);
+ make_edge (bb, successor_block (bb), 0);
}
/* Clean up the graph and warn for unreachable code. */
@@ -763,7 +765,7 @@ make_exit_edges (bb)
else if (FUNCTION_RECEIVES_NONLOCAL_GOTO (current_function_decl))
{
make_goto_expr_edges (bb);
- make_edge (bb, successor_block (bb), EDGE_FALLTHRU);
+ make_edge (bb, successor_block (bb), 0);
}
break;
@@ -779,7 +781,7 @@ make_exit_edges (bb)
&& FUNCTION_RECEIVES_NONLOCAL_GOTO (current_function_decl))
{
make_goto_expr_edges (bb);
- make_edge (bb, successor_block (bb), EDGE_FALLTHRU);
+ make_edge (bb, successor_block (bb), 0);
}
break;
@@ -2991,13 +2993,7 @@ bsi_commit_first_edge_insert (e, stmt)
}
/* Otherwise, create a new basic block, and split this edge. */
-
- if (e->flags & EDGE_ABNORMAL)
- abort();
-
- new_bb = create_bb ();
- redirect_edge_succ (e, new_bb);
- make_edge (new_bb, dest, EDGE_FALLTHRU);
+ new_bb = split_edge (e);
bb_ann = (bb_ann_t) xmalloc (sizeof (struct bb_ann_d));
new_bb->aux = bb_ann;
@@ -3347,3 +3343,35 @@ remap_stmts (basic_block bb1, basic_bloc
return false;
}
+
+/* Tree specific functions for the cfg loop optimizer. */
+
+/* Split a (typically critical) edge. Return the new block.
+ Abort on abnormal edges. */
+
+basic_block
+tree_split_edge (edge_in)
+ edge edge_in;
+{
+ basic_block new_bb, dest;
+
+ /* Abnormal edges cannot be split. */
+ if (edge_in->flags & EDGE_ABNORMAL)
+ abort ();
+
+ dest = edge_in->dest;
+ new_bb = create_bb ();
+ alloc_aux_for_block (new_bb, sizeof (struct bb_ann_d));
+ redirect_edge_succ (edge_in, new_bb);
+ make_edge (new_bb, dest, 0);
+ return new_bb;
+}
+
+/* Verifies that the flow information is ok. */
+
+void
+tree_verify_flow_info ()
+{
+
+}
+
Index: tree-optimize.c
===================================================================
RCS file: /home/pop/cvsroot/gcc-cvs/gcc/gcc/Attic/tree-optimize.c,v
retrieving revision 1.1.4.34
diff -u -3 -p -d -u -p -r1.1.4.34 tree-optimize.c
--- tree-optimize.c 28 Mar 2003 21:46:50 -0000 1.1.4.34
+++ tree-optimize.c 15 Apr 2003 12:33:19 -0000
@@ -36,6 +36,7 @@ Boston, MA 02111-1307, USA. */
#include "tree-flow.h"
#include "tree-dump.h"
#include "timevar.h"
+#include "cfgloop.h"
/* Rewrite a function tree to the SSA form and perform the SSA-based
optimizations on it. */
@@ -69,6 +70,11 @@ optimize_function_tree (fndecl)
/* Begin analysis and optimization passes. */
if (n_basic_blocks > 0 && ! (errorcount || sorrycount))
{
+ struct loops *loops;
+
+ loops = loop_optimizer_init (NULL);
+ loop_optimizer_finalize (loops, NULL);
+
/* Rewrite the function into SSA form. */
rewrite_into_ssa (fndecl);