summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog61
-rw-r--r--gcc/Makefile.in6
-rw-r--r--gcc/basic-block.h10
-rw-r--r--gcc/cfg.c8
-rw-r--r--gcc/cfgcleanup.c12
-rw-r--r--gcc/cfghooks.c48
-rw-r--r--gcc/cfghooks.h70
-rw-r--r--gcc/cfglayout.c92
-rw-r--r--gcc/cfglayout.h4
-rw-r--r--gcc/cfgloopmanip.c33
-rw-r--r--gcc/cfgrtl.c213
-rw-r--r--gcc/ifcvt.c6
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/toplev.c3
14 files changed, 427 insertions, 140 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 85e1b989a3a..af477d2eed6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,64 @@
+Fri Jun 6 11:02:35 CEST 2003 Jan Hubicka <jh@suse.cz>
+
+ * function.c (FLOOR_ROUND, CEIL_ROUND): Fix.
+ * i386.md (gen_pro_epilogue_adjust_stack): Deal with gigantic stack frames.
+ (pro_epilogue_adjust_stack_rex64_2): New pattern
+
+Fri Jun 6 11:03:14 CEST 2003 Jan Hubicka <jh@suse.cz>
+ Pop Sebastian
+ Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * cfghooks.h, cfghooks.c: New files.
+ * Makefile.in (BASIC_BLOCK_H): Depends on cfghooks.h.
+ (OBJS): Add cfghooks.o.
+ (cfghooks.o): New rule.
+ * basic-block.h (split_edge): Rename to rtl_split_edge.
+ (verify_flow_info): Rename to rtl_verify_flow_info.
+ (cfghooks.h): Included here.
+ * cfgrtl.c (split_edge): Renamed rtl_split_edge.
+ (verify_flow_info): Renamed rtl_verify_flow_info.
+ * toplev.c (rest_of_compilation): Call rtl_register_cfg_hooks.
+
+ * basic-block.h (split_block, split_edge, flow_delete_block,
+ redirect_edge_and_branch, redirect_edge_and_branch_force): Delete.
+ (flow_delete_block_noexpunge): Return void.
+ * cfg.c (verify_flow_info): New function.
+ * cfgcleanup.c (try_simplify_condjump, outgoing_edges_match,
+ try_crossjump_to_edge, try_optimize_cfg, delete_unreachable_blocks):
+ Use delete_block.
+ * cfglayout.c (function_footer): Rename to...
+ (cfg_layout_function_footer): ... this variable
+ (unlink_insn_chain): Make global.
+ (fixup_reorder_chain, record_effective_endpoints): Update.
+ (cleanup_unconditional_jumps): Use delete_block.
+ (cfg_layout_redirect_edge, cfg_layout_split_block): Move to cfgrtl.c
+ (cfg_layout_duplicate_bb): Use redirect_edge_and_branch_force.
+ (cfg_layout_initialize, cfg_layout_finalize): Update hooks.
+ * cfglayout.h (cfg_layout_redirect_edge, cfg_layout_split_block): Delete.
+ (cfg_layout_function_footer): Declare.
+ * cfgloopmanip (split_loop_bb): Do not update RBI.
+ (remove_bbs): Use delete_block.
+ (loop_reidrect_edge, loop_delete_branch_edge): Use
+ redirect_edge_and_branch.
+ (create_preheader): Use split_block and redirect_edge_and_branch_force.
+ (split_edge_with): Likewise.
+ * cfgrtl.c: Include cfglayout.h
+ (split_edge): Rename to ...
+ (rtl_split_edge) ... this one; make local.
+ (redirect_edge_and_branch): Rename to ...
+ (rtl_redirect_edge_and_branch) ... this one; make local.
+ (redirect_edge_and_branch_force): Rename to ...
+ (rtl_redirect_edge_and_branch_force) ... this one; make local.
+ (cfg_layout_delete_block, cfg_layout_delete_edge_and_branch_force): New.
+ (cfg_layout_redirect_edge_and_branch, cfg_layout_split_block): Move here from
+ cfglayout.c; update to directly call RTL counterparts.
+ (rtl_cfg_hooks, cfg_layout_rtl_cfg_hooks): New functions.
+ * ifcvt.c (find_cond_trap): Use delete_block.
+ (find_if_case_1): Use delete_block.
+ (find_if_case_2): Use delete_block.
+ * rtl.h (unlink_insn_chain): Declare.
+ * toplev.c (rtl_reigster_cfg_hooks): New.
+
2003-06-05 Richard Henderson <rth@redhat.com>
* recog.c (peephole2_optimize): Revert last change.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index f755afd1a0d..396744a1849 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -635,7 +635,7 @@ PARAMS_H = params.h params.def
TREE_H = tree.h tree.def $(MACHMODE_H) tree-check.h version.h builtins.def \
input.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
COVERAGE_H = coverage.h gcov-io.h gcov-iov.h
DEMANGLE_H = $(srcdir)/../include/demangle.h
RECOG_H = recog.h
@@ -820,7 +820,7 @@ OBJS = alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.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
@@ -1650,6 +1650,8 @@ flow.o : flow.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_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) 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
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 4c8d5e34dec..a229367c9ec 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -338,8 +338,6 @@ extern void update_bb_for_insn PARAMS ((basic_block));
extern void free_basic_block_vars PARAMS ((int));
-extern edge split_block PARAMS ((basic_block, rtx));
-extern basic_block split_edge PARAMS ((edge));
extern void insert_insn_on_edge PARAMS ((rtx, edge));
extern void commit_edge_insertions PARAMS ((void));
@@ -363,8 +361,7 @@ extern edge redirect_edge_succ_nodup PARAMS ((edge, basic_block));
extern void redirect_edge_pred PARAMS ((edge, basic_block));
extern basic_block create_basic_block_structure PARAMS ((rtx, rtx, rtx, basic_block));
extern basic_block create_basic_block PARAMS ((rtx, rtx, basic_block));
-extern int flow_delete_block PARAMS ((basic_block));
-extern int flow_delete_block_noexpunge PARAMS ((basic_block));
+extern void flow_delete_block_noexpunge PARAMS ((basic_block));
extern void clear_bb_flags PARAMS ((void));
extern void merge_blocks_nomove PARAMS ((basic_block, basic_block));
extern void tidy_fallthru_edge PARAMS ((edge, basic_block,
@@ -560,9 +557,7 @@ extern void compact_blocks PARAMS ((void));
extern basic_block alloc_block PARAMS ((void));
extern void find_unreachable_blocks PARAMS ((void));
extern int delete_noop_moves PARAMS ((rtx));
-extern basic_block redirect_edge_and_branch_force PARAMS ((edge, basic_block));
extern basic_block force_nonfallthru PARAMS ((edge));
-extern bool redirect_edge_and_branch PARAMS ((edge, basic_block));
extern rtx block_label PARAMS ((basic_block));
extern bool forwarder_block_p PARAMS ((basic_block));
extern bool purge_all_dead_edges PARAMS ((int));
@@ -649,4 +644,7 @@ extern void redirect_immediate_dominators PARAMS ((dominance_info, basic_block,
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 */
diff --git a/gcc/cfg.c b/gcc/cfg.c
index fe40007af41..7e4aa4035dc 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -828,3 +828,11 @@ free_aux_for_edges ()
clear_aux_for_edges ();
}
+
+/* Verify the CFG consistency.
+ ??? In the future move IL idepdendent checks here. */
+void
+verify_flow_info ()
+{
+ cfg_hooks->cfgh_verify_flow_info ();
+}
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index cfb838cf1f2..b61d287bca4 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -180,7 +180,7 @@ try_simplify_condjump (cbranch_block)
update_br_prob_note (cbranch_block);
/* Delete the block with the unconditional jump, and clean up the mess. */
- flow_delete_block (jump_block);
+ delete_block (jump_block);
tidy_fallthru_edge (cbranch_jump_edge, cbranch_block, cbranch_dest_block);
return true;
@@ -1271,7 +1271,7 @@ outgoing_edges_match (mode, bb1, bb2)
/* The labels should never be the same rtx. If they really are same
the jump tables are same too. So disable crossjumping of blocks BB1
and BB2 because when deleting the common insns in the end of BB1
- by flow_delete_block () the jump table would be deleted too. */
+ by delete_block () the jump table would be deleted too. */
/* If LABEL2 is referenced in BB1->END do not do anything
because we would loose information when replacing
LABEL1 by LABEL2 and then LABEL2 by LABEL1 in BB1->END. */
@@ -1568,7 +1568,7 @@ try_crossjump_to_edge (mode, e1, e2)
to_remove = redirect_from->succ->dest;
redirect_edge_and_branch_force (redirect_from->succ, redirect_to);
- flow_delete_block (to_remove);
+ delete_block (to_remove);
update_forwarder_flag (redirect_from);
@@ -1721,7 +1721,7 @@ try_optimize_cfg (mode)
fprintf (rtl_dump_file, "Deleting block %i.\n",
b->index);
- flow_delete_block (b);
+ delete_block (b);
changed = true;
b = c;
}
@@ -1772,7 +1772,7 @@ try_optimize_cfg (mode)
c = b->prev_bb == ENTRY_BLOCK_PTR ? b->next_bb : b->prev_bb;
redirect_edge_succ_nodup (b->pred, b->succ->dest);
- flow_delete_block (b);
+ delete_block (b);
changed = true;
b = c;
}
@@ -1871,7 +1871,7 @@ delete_unreachable_blocks ()
if (!(b->flags & BB_REACHABLE))
{
- flow_delete_block (b);
+ delete_block (b);
changed = true;
}
}
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
new file mode 100644
index 00000000000..d5815a12307
--- /dev/null
+++ b/gcc/cfghooks.c
@@ -0,0 +1,48 @@
+/* Hooks for cfg representation specific functions.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ Contributed by Sebastian Pop <s.pop@laposte.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"
+
+extern struct cfg_hooks rtl_cfg_hooks;
+extern struct cfg_hooks cfg_layout_rtl_cfg_hooks;
+
+/* A pointer to one of the hooks containers. */
+struct cfg_hooks *cfg_hooks;
+
+/* Initialization of functions specific to the rtl IR. */
+void
+rtl_register_cfg_hooks ()
+{
+ cfg_hooks = &rtl_cfg_hooks;
+}
+
+/* Initialization of functions specific to the rtl IR. */
+void
+cfg_layout_rtl_register_cfg_hooks ()
+{
+ cfg_hooks = &cfg_layout_rtl_cfg_hooks;
+}
diff --git a/gcc/cfghooks.h b/gcc/cfghooks.h
new file mode 100644
index 00000000000..c214b64cdc0
--- /dev/null
+++ b/gcc/cfghooks.h
@@ -0,0 +1,70 @@
+/* Hooks for cfg representation specific functions.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ Contributed by Sebastian Pop <s.pop@laposte.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
+{
+ /* Debugging. Do not use macros to hook these so they can be called from
+ debugger! */
+ void (*cfgh_verify_flow_info) PARAMS ((void));
+
+ /* Basic CFG manipulation. */
+
+ /* Redirect edge E to the given basic block B and update underlying program
+ representation. Returns false when edge is not easilly redirectable for
+ whatever reason. */
+ bool (*redirect_edge_and_branch) PARAMS ((edge e, basic_block b));
+
+ /* Same as the above but allows redirecting of fallthru edges. In that case
+ newly created forwarder basic block is returned. It aborts when called
+ on abnormal edge. */
+ basic_block (*redirect_edge_and_branch_force)PARAMS ((edge, basic_block));
+
+ /* Remove given basic block and all edges possibly pointing into it. */
+ void (*delete_block)PARAMS ((basic_block));
+
+ /* Split basic block B after specified instruction I. */
+ edge (*split_block) PARAMS ((basic_block b, void * i));
+
+ /* Higher level functions representable by primitive operations above if
+ we didn't have some oddities in RTL and Tree representations. */
+ basic_block (*cfgh_split_edge) PARAMS ((edge));
+};
+
+#define redirect_edge_and_branch(e,b) cfg_hooks->redirect_edge_and_branch (e,b)
+#define redirect_edge_and_branch_force(e,b) cfg_hooks->redirect_edge_and_branch_force (e,b)
+#define split_block(e,i) cfg_hooks->split_block (e,i)
+#define delete_block(b) cfg_hooks->delete_block (b)
+#define split_edge(e) cfg_hooks->cfgh_split_edge (e)
+
+/* Hooks containers. */
+extern struct cfg_hooks rtl_cfg_hooks;
+
+/* A pointer to one of the hooks containers. */
+extern struct cfg_hooks *cfg_hooks;
+
+/* Declarations. */
+extern void rtl_register_cfg_hooks PARAMS ((void));
+extern void cfg_layout_rtl_register_cfg_hooks PARAMS ((void));
+
+#endif /* GCC_CFGHOOKS_H */
diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c
index 9c5b85aec16..bf41013b9eb 100644
--- a/gcc/cfglayout.c
+++ b/gcc/cfglayout.c
@@ -39,7 +39,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
extern struct obstack flow_obstack;
/* Holds the interesting trailing notes for the function. */
-static rtx function_footer;
+rtx cfg_layout_function_footer;
static rtx skip_insns_after_block PARAMS ((basic_block));
static void record_effective_endpoints PARAMS ((void));
@@ -52,11 +52,10 @@ static void change_scope PARAMS ((rtx, tree, tree));
void verify_insn_chain PARAMS ((void));
static void cleanup_unconditional_jumps PARAMS ((struct loops *));
static void fixup_fallthru_exit_predecessor PARAMS ((void));
-static rtx unlink_insn_chain PARAMS ((rtx, rtx));
static rtx duplicate_insn_chain PARAMS ((rtx, rtx));
static void break_superblocks PARAMS ((void));
-static rtx
+rtx
unlink_insn_chain (first, last)
rtx first;
rtx last;
@@ -208,9 +207,9 @@ record_effective_endpoints ()
next_insn = NEXT_INSN (bb->end);
}
- function_footer = next_insn;
- if (function_footer)
- function_footer = unlink_insn_chain (function_footer, get_last_insn ());
+ cfg_layout_function_footer = next_insn;
+ if (cfg_layout_function_footer)
+ cfg_layout_function_footer = unlink_insn_chain (cfg_layout_function_footer, get_last_insn ());
}
/* Build a varray mapping INSN_UID to lexical block. Return it. */
@@ -423,9 +422,9 @@ fixup_reorder_chain ()
if (index != n_basic_blocks)
abort ();
- NEXT_INSN (insn) = function_footer;
- if (function_footer)
- PREV_INSN (function_footer) = insn;
+ NEXT_INSN (insn) = cfg_layout_function_footer;
+ if (cfg_layout_function_footer)
+ PREV_INSN (cfg_layout_function_footer) = insn;
while (NEXT_INSN (insn))
insn = NEXT_INSN (insn);
@@ -696,7 +695,7 @@ cleanup_unconditional_jumps (loops)
}
redirect_edge_succ_nodup (bb->pred, bb->succ->dest);
- flow_delete_block (bb);
+ delete_block (bb);
bb = prev;
}
else if (simplejump_p (bb->end))
@@ -888,75 +887,6 @@ duplicate_insn_chain (from, to)
delete_insn (last);
return insn;
}
-
-/* Redirect Edge to DEST. */
-bool
-cfg_layout_redirect_edge (e, dest)
- edge e;
- basic_block dest;
-{
- basic_block src = e->src;
- basic_block old_next_bb = src->next_bb;
- bool ret;
-
- /* Redirect_edge_and_branch may decide to turn branch into fallthru edge
- in the case the basic block appears to be in sequence. Avoid this
- transformation. */
-
- src->next_bb = NULL;
- if (e->flags & EDGE_FALLTHRU)
- {
- /* Redirect any branch edges unified with the fallthru one. */
- if (GET_CODE (src->end) == JUMP_INSN
- && JUMP_LABEL (src->end) == e->dest->head)
- {
- if (!redirect_jump (src->end, block_label (dest), 0))
- abort ();
- }
- /* In case we are redirecting fallthru edge to the branch edge
- of conditional jump, remove it. */
- if (src->succ->succ_next
- && !src->succ->succ_next->succ_next)
- {
- edge s = e->succ_next ? e->succ_next : src->succ;
- if (s->dest == dest
- && any_condjump_p (src->end)
- && onlyjump_p (src->end))
- delete_insn (src->end);
- }
- redirect_edge_succ_nodup (e, dest);
-
- ret = true;
- }
- else
- ret = redirect_edge_and_branch (e, dest);
-
- /* We don't want simplejumps in the insn stream during cfglayout. */
- if (simplejump_p (src->end))
- {
- delete_insn (src->end);
- delete_barrier (NEXT_INSN (src->end));
- src->succ->flags |= EDGE_FALLTHRU;
- }
- src->next_bb = old_next_bb;
-
- return ret;
-}
-
-/* Same as split_block but update cfg_layout structures. */
-edge
-cfg_layout_split_block (bb, insn)
- basic_block bb;
- rtx insn;
-{
- edge fallthru = split_block (bb, insn);
-
- alloc_aux_for_block (fallthru->dest, sizeof (struct reorder_block_def));
- RBI (fallthru->dest)->footer = RBI (fallthru->src)->footer;
- RBI (fallthru->src)->footer = NULL;
- return fallthru;
-}
-
/* Create a duplicate of the basic block BB and redirect edge E into it. */
basic_block
@@ -1037,7 +967,7 @@ cfg_layout_duplicate_bb (bb, e)
new_bb->frequency = EDGE_FREQUENCY (e);
bb->frequency -= EDGE_FREQUENCY (e);
- cfg_layout_redirect_edge (e, new_bb);
+ redirect_edge_and_branch_force (e, new_bb);
}
if (bb->count < 0)
@@ -1060,6 +990,7 @@ cfg_layout_initialize (loops)
/* Our algorithm depends on fact that there are now dead jumptables
around the code. */
alloc_aux_for_blocks (sizeof (struct reorder_block_def));
+ cfg_layout_rtl_register_cfg_hooks ();
cleanup_unconditional_jumps (loops);
@@ -1101,6 +1032,7 @@ break_superblocks ()
void
cfg_layout_finalize ()
{
+ rtl_register_cfg_hooks ();
fixup_fallthru_exit_predecessor ();
fixup_reorder_chain ();
diff --git a/gcc/cfglayout.h b/gcc/cfglayout.h
index aec5e7ebba3..48f11af753b 100644
--- a/gcc/cfglayout.h
+++ b/gcc/cfglayout.h
@@ -35,11 +35,11 @@ typedef struct reorder_block_def
#define RBI(BB) ((reorder_block_def) (BB)->aux)
+extern rtx cfg_layout_function_footer;
+
extern void cfg_layout_initialize PARAMS ((struct loops *));
extern void cfg_layout_finalize PARAMS ((void));
extern bool cfg_layout_can_duplicate_bb_p PARAMS ((basic_block));
extern basic_block cfg_layout_duplicate_bb PARAMS ((basic_block, edge));
extern void scope_to_insns_initialize PARAMS ((void));
extern void scope_to_insns_finalize PARAMS ((void));
-extern bool cfg_layout_redirect_edge PARAMS ((edge, basic_block));
-extern edge cfg_layout_split_block PARAMS ((basic_block, rtx));
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c
index 70926f2ab7d..1e878a5b7d4 100644
--- a/gcc/cfgloopmanip.c
+++ b/gcc/cfgloopmanip.c
@@ -86,9 +86,6 @@ split_loop_bb (loops, bb, insn)
free (dom_bbs);
set_immediate_dominator (loops->cfg.dom, e->dest, e->src);
- /* Take care of RBI. */
- alloc_aux_for_block (e->dest, sizeof (struct reorder_block_def));
-
return e;
}
@@ -123,7 +120,7 @@ remove_bbs (dom, bbs, nbbs)
{
remove_bb_from_loops (bbs[i]);
delete_from_dominance_info (dom, bbs[i]);
- flow_delete_block (bbs[i]);
+ delete_block (bbs[i]);
}
}
@@ -828,7 +825,7 @@ loop_redirect_edge (e, dest)
if (e->dest == dest)
return;
- cfg_layout_redirect_edge (e, dest);
+ redirect_edge_and_branch_force (e, dest);
}
/* Deletes edge E from a branch if possible. Unless REALLY_DELETE is set,
@@ -865,7 +862,7 @@ loop_delete_branch_edge (e, really_delete)
/* Redirecting behaves wrongly wrto this flag. */
irr = snd->flags & EDGE_IRREDUCIBLE_LOOP;
- if (!cfg_layout_redirect_edge (e, newdest))
+ if (!redirect_edge_and_branch (e, newdest))
return false;
src->succ->flags &= ~EDGE_IRREDUCIBLE_LOOP;
src->succ->flags |= irr;
@@ -1396,10 +1393,7 @@ create_preheader (loop, dom, flags)
/* Split_block would not split block after its end. */
emit_note_after (NOTE_INSN_DELETED, insn);
}
- if (flags & CP_INSIDE_CFGLAYOUT)
- fallthru = cfg_layout_split_block (loop->header, insn);
- else
- fallthru = split_block (loop->header, insn);
+ fallthru = split_block (loop->header, insn);
dummy = fallthru->src;
loop->header = fallthru->dest;
@@ -1424,18 +1418,13 @@ create_preheader (loop, dom, flags)
dummy->frequency -= EDGE_FREQUENCY (e);
dummy->count -= e->count;
fallthru->count -= e->count;
- if (flags & CP_INSIDE_CFGLAYOUT)
- cfg_layout_redirect_edge (e, loop->header);
- else
+ jump = redirect_edge_and_branch_force (e, loop->header);
+ if (jump)
{
- jump = redirect_edge_and_branch_force (e, loop->header);
- if (jump)
- {
- add_to_dominance_info (dom, jump);
- set_immediate_dominator (dom, jump, src);
- add_bb_to_loop (jump, loop);
- loop->latch = jump;
- }
+ add_to_dominance_info (dom, jump);
+ set_immediate_dominator (dom, jump, src);
+ add_bb_to_loop (jump, loop);
+ loop->latch = jump;
}
/* Update structures. */
@@ -1524,7 +1513,7 @@ loop_split_edge_with (e, insns, loops)
new_bb->count = e->count;
new_bb->frequency = EDGE_FREQUENCY (e);
- cfg_layout_redirect_edge (e, new_bb);
+ redirect_edge_and_branch_force (e, new_bb);
alloc_aux_for_block (new_bb, sizeof (struct reorder_block_def));
if (insns)
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 0ba32c5782e..b0678f09f1c 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -26,7 +26,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- CFG-aware instruction chain manipulation
delete_insn, delete_insn_chain
- Basic block manipulation
- create_basic_block, flow_delete_block, split_block,
+ create_basic_block, rtl_delete_block,rtl_split_block,
merge_blocks_nomove
- Infrastructure to determine quickly basic block for insn
compute_bb_for_insn, update_bb_for_insn, set_block_for_insn,
@@ -59,6 +59,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tm_p.h"
#include "obstack.h"
#include "insn-config.h"
+#include "cfglayout.h"
/* Stubs in case we don't have a return insn. */
#ifndef HAVE_return
@@ -79,6 +80,16 @@ static bool try_redirect_by_replacing_jump PARAMS ((edge, basic_block));
static rtx last_loop_beg_note PARAMS ((rtx));
static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block));
basic_block force_nonfallthru_and_redirect PARAMS ((edge, basic_block));
+static basic_block rtl_split_edge PARAMS ((edge));
+static void rtl_verify_flow_info PARAMS ((void));
+static edge cfg_layout_split_block PARAMS ((basic_block, void *));
+static bool cfg_layout_redirect_edge_and_branch PARAMS ((edge, basic_block));
+static basic_block cfg_layout_redirect_edge_and_branch_force PARAMS ((edge, basic_block));
+static void cfg_layout_delete_block PARAMS ((basic_block));
+static void rtl_delete_block PARAMS ((basic_block));
+static basic_block rtl_redirect_edge_and_branch_force PARAMS ((edge, basic_block));
+static bool rtl_redirect_edge_and_branch PARAMS ((edge, basic_block));
+static edge rtl_split_block PARAMS ((basic_block, void *));
/* Return true if NOTE is not one of the ones that must be kept paired,
so that we may simply delete it. */
@@ -348,11 +359,10 @@ create_basic_block (head, end, after)
/* ??? Preserving all such notes strikes me as wrong. It would be nice
to post-process the stream to remove empty blocks, loops, ranges, etc. */
-int
+void
flow_delete_block_noexpunge (b)
basic_block b;
{
- int deleted_handler = 0;
rtx insn, end, tmp;
/* If the head of this block is a CODE_LABEL, then it might be the
@@ -404,20 +414,16 @@ flow_delete_block_noexpunge (b)
b->pred = NULL;
b->succ = NULL;
-
- return deleted_handler;
}
-int
-flow_delete_block (b)
+static void
+rtl_delete_block (b)
basic_block b;
{
- int deleted_handler = flow_delete_block_noexpunge (b);
+ flow_delete_block_noexpunge (b);
/* Remove the basic block from the array. */
expunge_block (b);
-
- return deleted_handler;
}
/* Records the basic block struct in BLOCK_FOR_INSN for every insn. */
@@ -474,14 +480,15 @@ update_bb_for_insn (bb)
this function renumbers all the basic blocks so that the new
one has a number one greater than the block split. */
-edge
-split_block (bb, insn)
+static edge
+rtl_split_block (bb, insnp)
basic_block bb;
- rtx insn;
+ void *insnp;
{
basic_block new_bb;
edge new_edge;
edge e;
+ rtx insn = insnp;
/* There is no point splitting the block after its end. */
if (bb->end == insn)
@@ -811,8 +818,8 @@ last_loop_beg_note (insn)
already destinated TARGET and we didn't managed to simplify instruction
stream. */
-bool
-redirect_edge_and_branch (e, target)
+static bool
+rtl_redirect_edge_and_branch (e, target)
edge e;
basic_block target;
{
@@ -1076,8 +1083,8 @@ force_nonfallthru (e)
basic block. Return new basic block if created, NULL otherwise.
Abort if conversion is impossible. */
-basic_block
-redirect_edge_and_branch_force (e, target)
+static basic_block
+rtl_redirect_edge_and_branch_force (e, target)
edge e;
basic_block target;
{
@@ -1230,7 +1237,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;
@@ -1741,7 +1748,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 ();
@@ -2363,3 +2370,171 @@ purge_all_dead_edges (update_life_p)
sbitmap_free (blocks);
return purged;
}
+
+/* Same as split_block but update cfg_layout structures. */
+static edge
+cfg_layout_split_block (bb, insnp)
+ basic_block bb;
+ void *insnp;
+{
+ rtx insn = insnp;
+
+ edge fallthru = rtl_split_block (bb, insn);
+
+ alloc_aux_for_block (fallthru->dest, sizeof (struct reorder_block_def));
+ RBI (fallthru->dest)->footer = RBI (fallthru->src)->footer;
+ RBI (fallthru->src)->footer = NULL;
+ return fallthru;
+}
+
+
+/* Redirect Edge to DEST. */
+static bool
+cfg_layout_redirect_edge_and_branch (e, dest)
+ edge e;
+ basic_block dest;
+{
+ basic_block src = e->src;
+ basic_block old_next_bb = src->next_bb;
+ bool ret;
+
+ /* Redirect_edge_and_branch may decide to turn branch into fallthru edge
+ in the case the basic block appears to be in sequence. Avoid this
+ transformation. */
+
+ src->next_bb = NULL;
+ if (e->flags & EDGE_FALLTHRU)
+ {
+ /* Redirect any branch edges unified with the fallthru one. */
+ if (GET_CODE (src->end) == JUMP_INSN
+ && JUMP_LABEL (src->end) == e->dest->head)
+ {
+ if (!redirect_jump (src->end, block_label (dest), 0))
+ abort ();
+ }
+ /* In case we are redirecting fallthru edge to the branch edge
+ of conditional jump, remove it. */
+ if (src->succ->succ_next
+ && !src->succ->succ_next->succ_next)
+ {
+ edge s = e->succ_next ? e->succ_next : src->succ;
+ if (s->dest == dest
+ && any_condjump_p (src->end)
+ && onlyjump_p (src->end))
+ delete_insn (src->end);
+ }
+ redirect_edge_succ_nodup (e, dest);
+
+ ret = true;
+ }
+ else
+ ret = rtl_redirect_edge_and_branch (e, dest);
+
+ /* We don't want simplejumps in the insn stream during cfglayout. */
+ if (simplejump_p (src->end))
+ {
+ delete_insn (src->end);
+ delete_barrier (NEXT_INSN (src->end));
+ src->succ->flags |= EDGE_FALLTHRU;
+ }
+ src->next_bb = old_next_bb;
+
+ return ret;
+}
+
+/* Simple wrapper as we always can redirect fallthru edges. */
+static basic_block
+cfg_layout_redirect_edge_and_branch_force (e, dest)
+ edge e;
+ basic_block dest;
+{
+ if (!cfg_layout_redirect_edge_and_branch (e, dest))
+ abort ();
+ return NULL;
+}
+
+/* Same as flow_delete_block but update cfg_layout structures. */
+static void
+cfg_layout_delete_block (bb)
+ basic_block bb;
+{
+ rtx insn, next, prev = PREV_INSN (bb->head), *to, remaints;
+
+ if (RBI (bb)->header)
+ {
+ next = bb->head;
+ if (prev)
+ NEXT_INSN (prev) = RBI (bb)->header;
+ else
+ set_first_insn (RBI (bb)->header);
+ PREV_INSN (RBI (bb)->header) = prev;
+ insn = RBI (bb)->header;
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ NEXT_INSN (insn) = next;
+ PREV_INSN (next) = insn;
+ }
+ next = NEXT_INSN (bb->end);
+ if (RBI (bb)->footer)
+ {
+ insn = bb->end;
+ NEXT_INSN (insn) = RBI (bb)->footer;
+ PREV_INSN (RBI (bb)->footer) = insn;
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ NEXT_INSN (insn) = next;
+ if (next)
+ PREV_INSN (next) = insn;
+ else
+ set_last_insn (insn);
+ }
+ if (bb->next_bb != EXIT_BLOCK_PTR)
+ to = &RBI(bb->next_bb)->header;
+ else
+ to = &cfg_layout_function_footer;
+ rtl_delete_block (bb);
+
+ if (prev)
+ prev = NEXT_INSN (prev);
+ else
+ prev = get_insns ();
+ if (next)
+ next = PREV_INSN (next);
+ else
+ next = get_last_insn ();
+
+ if (next && NEXT_INSN (next) != prev)
+ {
+ remaints = unlink_insn_chain (prev, next);
+ insn = remaints;
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ NEXT_INSN (insn) = *to;
+ if (*to)
+ PREV_INSN (*to) = insn;
+ *to = remaints;
+ }
+}
+
+/* Implementation of CFG manipulation for linearized RTL. */
+struct cfg_hooks rtl_cfg_hooks = {
+ rtl_verify_flow_info,
+ rtl_redirect_edge_and_branch,
+ rtl_redirect_edge_and_branch_force,
+ rtl_delete_block,
+ rtl_split_block,
+ rtl_split_edge
+};
+
+/* Implementation of CFG manipulation for cfg layout RTL, where
+ basic block connected via fallthru edges does not have to be adjacent.
+ This representation will hopefully become the default one in future
+ version of the compiler. */
+struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
+ NULL, /* verify_flow_info. */
+ cfg_layout_redirect_edge_and_branch,
+ cfg_layout_redirect_edge_and_branch_force,
+ cfg_layout_delete_block,
+ cfg_layout_split_block,
+ NULL /* split_edge. */
+};
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index caa54c56b13..baac0413176 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -2547,7 +2547,7 @@ find_cond_trap (test_bb, then_edge, else_edge)
{
if (post_dominators)
delete_from_dominance_info (post_dominators, trap_bb);
- flow_delete_block (trap_bb);
+ delete_block (trap_bb);
num_removed_blocks++;
}
@@ -2736,7 +2736,7 @@ find_if_case_1 (test_bb, then_edge, else_edge)
then_bb_index = then_bb->index;
if (post_dominators)
delete_from_dominance_info (post_dominators, then_bb);
- flow_delete_block (then_bb);
+ delete_block (then_bb);
/* Make rest of code believe that the newly created block is the THEN_BB
block we removed. */
@@ -2818,7 +2818,7 @@ find_if_case_2 (test_bb, then_edge, else_edge)
if (post_dominators)
delete_from_dominance_info (post_dominators, else_bb);
- flow_delete_block (else_bb);
+ delete_block (else_bb);
num_removed_blocks++;
num_updated_if_blocks++;
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 8a76fe2a267..21998a605ff 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2082,6 +2082,7 @@ extern void renumber_insns PARAMS ((FILE *));
extern void remove_unnecessary_notes PARAMS ((void));
extern rtx delete_insn PARAMS ((rtx));
extern void delete_insn_chain PARAMS ((rtx, rtx));
+extern rtx unlink_insn_chain PARAMS ((rtx, rtx));
extern rtx delete_insn_and_edges PARAMS ((rtx));
extern void delete_insn_chain_and_edges PARAMS ((rtx, rtx));
diff --git a/gcc/toplev.c b/gcc/toplev.c
index f005f0418ff..1a82946a8a6 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -3472,6 +3472,9 @@ rest_of_compilation (tree decl)
timevar_push (TV_REST_OF_COMPILATION);
+ /* Register rtl specific functions for cfg. */
+ rtl_register_cfg_hooks ();
+
/* Now that we're out of the frontend, we shouldn't have any more
CONCATs anywhere. */
generating_concat_p = 0;