function.c (FLOOR_ROUND, CEIL_ROUND): Fix.
* 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 * 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. From-SVN: r67535
This commit is contained in:
parent
7654db1b66
commit
9ee634e345
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
48
gcc/cfghooks.c
Normal file
48
gcc/cfghooks.c
Normal file
@ -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;
|
||||
}
|
70
gcc/cfghooks.h
Normal file
70
gcc/cfghooks.h
Normal file
@ -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 */
|
@ -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 ();
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
|
213
gcc/cfgrtl.c
213
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. */
|
||||
};
|
||||
|
@ -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++;
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user