aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2002-02-09 02:18:12 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2002-02-09 02:18:12 +0000
commite4ec2cac3fd5c2d19dcece8c95644c30cb52e344 (patch)
tree923f3420128e009083834e0d815322b5f11fff42
parentb6459d9a78a55b0a1906357552ccff2d2769fa8a (diff)
downloadgcc-e4ec2cac3fd5c2d19dcece8c95644c30cb52e344.zip
gcc-e4ec2cac3fd5c2d19dcece8c95644c30cb52e344.tar.gz
gcc-e4ec2cac3fd5c2d19dcece8c95644c30cb52e344.tar.bz2
hooks.c: New file.
* hooks.c: New file. * hooks.h: New file. * Makefile.in (HOOKS_H): New. (TARGET_DEF_H): Added $(HOOKS_H). (OBJS): Added hooks.o. (cfgcleanup.o, bb-reorder.o): Added target.h. (hooks.o): Added dependencies. * target-def.h (TARGET_CANNOT_MODIFY_JUMPS_P): New, added to... (TARGET_INITIALIZER): this. * doc/tm.texi (TARGET_CANNOT_MODIFY_JUMPS_P): Document. * target.h (struct gcc_target): Added cannot_modify_jumps_p. * bb-reorder.c: Include target.h. (reorder_basic_blocks): Skip if cannot modify jumps. * cfgcleanup.c: Include target.h. (try_optimize_cfg): Skip merge blocking if cannot modify jumps. From-SVN: r49627
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/Makefile.in12
-rw-r--r--gcc/bb-reorder.c6
-rw-r--r--gcc/cfgcleanup.c256
-rw-r--r--gcc/doc/tm.texi15
-rw-r--r--gcc/hooks.c34
-rw-r--r--gcc/hooks.h22
-rw-r--r--gcc/target-def.h8
-rw-r--r--gcc/target.h4
9 files changed, 245 insertions, 130 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7ce7496..7c2267c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2002-02-09 Alexandre Oliva <aoliva@redhat.com>
+
+ * hooks.c: New file.
+ * hooks.h: New file.
+ * Makefile.in (HOOKS_H): New.
+ (TARGET_DEF_H): Added $(HOOKS_H).
+ (OBJS): Added hooks.o.
+ (cfgcleanup.o, bb-reorder.o): Added target.h.
+ (hooks.o): Added dependencies.
+ * target-def.h (TARGET_CANNOT_MODIFY_JUMPS_P): New, added to...
+ (TARGET_INITIALIZER): this.
+ * doc/tm.texi (TARGET_CANNOT_MODIFY_JUMPS_P): Document.
+ * target.h (struct gcc_target): Added cannot_modify_jumps_p.
+ * bb-reorder.c: Include target.h.
+ (reorder_basic_blocks): Skip if cannot modify jumps.
+ * cfgcleanup.c: Include target.h.
+ (try_optimize_cfg): Skip merge blocking if cannot modify jumps.
+
2002-02-08 Chris Demetriou <cgd@broadcom.com>
* config/mips/mips.md (casesi_internal, casesi_internal_di):
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index f21ed3d..59f1d3a 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -543,7 +543,8 @@ HCONFIG_H = hconfig.h $(build_xm_file_list)
CONFIG_H = $(GCONFIG_H) insn-constants.h insn-flags.h
TCONFIG_H = tconfig.h $(xm_file_list)
TARGET_H = target.h
-TARGET_DEF_H = target-def.h
+HOOKS_H = hooks.h
+TARGET_DEF_H = target-def.h $(HOOKS_H)
TM_P_H = tm_p.h $(tm_p_file_list) tm-preds.h
MACHMODE_H = machmode.h machmode.def
@@ -718,7 +719,7 @@ OBJS = alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
df.o diagnostic.o doloop.o dominance.o dwarf2asm.o dwarf2out.o dwarfout.o \
emit-rtl.o except.o explow.o expmed.o expr.o final.o flow.o \
fold-const.o function.o gcse.o genrtl.o ggc-common.o global.o graph.o \
- haifa-sched.o hash.o hashtable.o ifcvt.o insn-attrtab.o insn-emit.o \
+ haifa-sched.o hash.o hashtable.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o \
insn-extract.o insn-opinit.o insn-output.o insn-peep.o insn-recog.o \
integrate.o intl.o jump.o langhooks.o lcm.o lists.o local-alloc.o \
loop.o mbchar.o optabs.o params.o predict.o print-rtl.o print-tree.o \
@@ -1495,7 +1496,7 @@ cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h insn-config.h \
function.h except.h $(GGC_H)
cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TIMEVAR_H)\
$(BASIC_BLOCK_H) hard-reg-set.h output.h flags.h $(RECOG_H) toplev.h \
- $(GGC_H) insn-config.h cselib.h $(TM_P_H)
+ $(GGC_H) insn-config.h cselib.h $(TARGET_H) $(TM_P_H)
cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(BASIC_BLOCK_H) hard-reg-set.h
dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h \
@@ -1564,8 +1565,8 @@ predict.o: predict.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_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 $(EXPR_H) $(TM_P_H) $(PREDICT_H)
lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) $(GGC_H)
-bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
- $(BASIC_BLOCK_H) hard-reg-set.h output.h cfglayout.h
+bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
+ flags.h $(BASIC_BLOCK_H) hard-reg-set.h output.h cfglayout.h $(TARGET_H)
cfglayout.o : cfglayout.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
insn-config.h $(BASIC_BLOCK_H) hard-reg-set.h output.h function.h \
cfglayout.h
@@ -1579,6 +1580,7 @@ ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) toplev.h \
dependence.o : dependence.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
$(C_COMMON_H) flags.h varray.h $(EXPR_H)
params.o : params.c $(CONFIG_H) $(SYSTEM_H) $(PARAMS_H) toplev.h
+hooks.o: hooks.c $(CONFIG_H) $(SYSTEM_H) $(HOOKS_H)
$(out_object_file): $(out_file) $(CONFIG_H) $(TREE_H) $(GGC_H) \
$(RTL_H) $(REGS_H) hard-reg-set.h real.h insn-config.h conditions.h \
diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index 97ad142..2578604 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -1,5 +1,5 @@
/* Basic block reordering routines for the GNU compiler.
- Copyright (C) 2000 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -89,6 +89,7 @@
#include "flags.h"
#include "output.h"
#include "cfglayout.h"
+#include "target.h"
/* Local function prototypes. */
static void make_reorder_chain PARAMS ((void));
@@ -260,6 +261,9 @@ reorder_basic_blocks ()
if (n_basic_blocks <= 1)
return;
+ if ((* targetm.cannot_modify_jumps_p) ())
+ return;
+
cfg_layout_initialize ();
make_reorder_chain ();
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 13c5a8e..d9f9cf2 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -44,6 +44,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "toplev.h"
#include "cselib.h"
#include "tm_p.h"
+#include "target.h"
#include "obstack.h"
@@ -1531,149 +1532,158 @@ try_optimize_cfg (mode)
for (i = 0; i < n_basic_blocks; i++)
update_forwarder_flag (BASIC_BLOCK (i));
- /* Attempt to merge blocks as made possible by edge removal. If a block
- has only one successor, and the successor has only one predecessor,
- they may be combined. */
- do
+ if (! (* targetm.cannot_modify_jumps_p) ())
{
- changed = false;
- iterations++;
-
- if (rtl_dump_file)
- fprintf (rtl_dump_file, "\n\ntry_optimize_cfg iteration %i\n\n",
- iterations);
-
- for (i = 0; i < n_basic_blocks;)
+ /* Attempt to merge blocks as made possible by edge removal. If
+ a block has only one successor, and the successor has only
+ one predecessor, they may be combined. */
+ do
{
- basic_block c, b = BASIC_BLOCK (i);
- edge s;
- bool changed_here = false;
+ changed = false;
+ iterations++;
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file,
+ "\n\ntry_optimize_cfg iteration %i\n\n",
+ iterations);
- /* Delete trivially dead basic blocks. */
- while (b->pred == NULL)
+ for (i = 0; i < n_basic_blocks;)
{
- c = BASIC_BLOCK (b->index - 1);
- if (rtl_dump_file)
- fprintf (rtl_dump_file, "Deleting block %i.\n", b->index);
+ basic_block c, b = BASIC_BLOCK (i);
+ edge s;
+ bool changed_here = false;
- flow_delete_block (b);
- changed = true;
- b = c;
- }
+ /* Delete trivially dead basic blocks. */
+ while (b->pred == NULL)
+ {
+ c = BASIC_BLOCK (b->index - 1);
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Deleting block %i.\n",
+ b->index);
+
+ flow_delete_block (b);
+ changed = true;
+ b = c;
+ }
- /* Remove code labels no longer used. Don't do this before
- CALL_PLACEHOLDER is removed, as some branches may be hidden
- within. */
- if (b->pred->pred_next == NULL
- && (b->pred->flags & EDGE_FALLTHRU)
- && !(b->pred->flags & EDGE_COMPLEX)
- && GET_CODE (b->head) == CODE_LABEL
- && (!(mode & CLEANUP_PRE_SIBCALL)
- || !tail_recursion_label_p (b->head))
- /* If the previous block ends with a branch to this block,
- we can't delete the label. Normally this is a condjump
- that is yet to be simplified, but if CASE_DROPS_THRU,
- this can be a tablejump with some element going to the
- same place as the default (fallthru). */
- && (b->pred->src == ENTRY_BLOCK_PTR
- || GET_CODE (b->pred->src->end) != JUMP_INSN
- || ! label_is_jump_target_p (b->head, b->pred->src->end)))
- {
- rtx label = b->head;
+ /* Remove code labels no longer used. Don't do this
+ before CALL_PLACEHOLDER is removed, as some branches
+ may be hidden within. */
+ if (b->pred->pred_next == NULL
+ && (b->pred->flags & EDGE_FALLTHRU)
+ && !(b->pred->flags & EDGE_COMPLEX)
+ && GET_CODE (b->head) == CODE_LABEL
+ && (!(mode & CLEANUP_PRE_SIBCALL)
+ || !tail_recursion_label_p (b->head))
+ /* If the previous block ends with a branch to this
+ block, we can't delete the label. Normally this
+ is a condjump that is yet to be simplified, but
+ if CASE_DROPS_THRU, this can be a tablejump with
+ some element going to the same place as the
+ default (fallthru). */
+ && (b->pred->src == ENTRY_BLOCK_PTR
+ || GET_CODE (b->pred->src->end) != JUMP_INSN
+ || ! label_is_jump_target_p (b->head,
+ b->pred->src->end)))
+ {
+ rtx label = b->head;
- b->head = NEXT_INSN (b->head);
- delete_insn_chain (label, label);
- if (rtl_dump_file)
- fprintf (rtl_dump_file, "Deleted label in block %i.\n",
- b->index);
- }
+ b->head = NEXT_INSN (b->head);
+ delete_insn_chain (label, label);
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Deleted label in block %i.\n",
+ b->index);
+ }
- /* If we fall through an empty block, we can remove it. */
- if (b->pred->pred_next == NULL
- && (b->pred->flags & EDGE_FALLTHRU)
- && GET_CODE (b->head) != CODE_LABEL
- && FORWARDER_BLOCK_P (b)
- /* Note that forwarder_block_p true ensures that there
- is a successor for this block. */
- && (b->succ->flags & EDGE_FALLTHRU)
- && n_basic_blocks > 1)
- {
- if (rtl_dump_file)
- fprintf (rtl_dump_file, "Deleting fallthru block %i.\n",
- b->index);
+ /* If we fall through an empty block, we can remove it. */
+ if (b->pred->pred_next == NULL
+ && (b->pred->flags & EDGE_FALLTHRU)
+ && GET_CODE (b->head) != CODE_LABEL
+ && FORWARDER_BLOCK_P (b)
+ /* Note that forwarder_block_p true ensures that
+ there is a successor for this block. */
+ && (b->succ->flags & EDGE_FALLTHRU)
+ && n_basic_blocks > 1)
+ {
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file,
+ "Deleting fallthru block %i.\n",
+ b->index);
+
+ c = BASIC_BLOCK (b->index ? b->index - 1 : 1);
+ redirect_edge_succ_nodup (b->pred, b->succ->dest);
+ flow_delete_block (b);
+ changed = true;
+ b = c;
+ }
- c = BASIC_BLOCK (b->index ? b->index - 1 : 1);
- redirect_edge_succ_nodup (b->pred, b->succ->dest);
- flow_delete_block (b);
- changed = true;
- b = c;
- }
+ /* Merge blocks. Loop because chains of blocks might be
+ combineable. */
+ while ((s = b->succ) != NULL
+ && s->succ_next == NULL
+ && !(s->flags & EDGE_COMPLEX)
+ && (c = s->dest) != EXIT_BLOCK_PTR
+ && c->pred->pred_next == NULL
+ /* If the jump insn has side effects,
+ we can't kill the edge. */
+ && (GET_CODE (b->end) != JUMP_INSN
+ || onlyjump_p (b->end))
+ && merge_blocks (s, b, c, mode))
+ changed_here = true;
+
+ /* Simplify branch over branch. */
+ if ((mode & CLEANUP_EXPENSIVE) && try_simplify_condjump (b))
+ {
+ BB_SET_FLAG (b, BB_UPDATE_LIFE);
+ changed_here = true;
+ }
- /* Merge blocks. Loop because chains of blocks might be
- combineable. */
- while ((s = b->succ) != NULL
- && s->succ_next == NULL
- && !(s->flags & EDGE_COMPLEX)
- && (c = s->dest) != EXIT_BLOCK_PTR
- && c->pred->pred_next == NULL
- /* If the jump insn has side effects,
- we can't kill the edge. */
- && (GET_CODE (b->end) != JUMP_INSN
- || onlyjump_p (b->end))
- && merge_blocks (s, b, c, mode))
- changed_here = true;
-
- /* Simplify branch over branch. */
- if ((mode & CLEANUP_EXPENSIVE) && try_simplify_condjump (b))
- {
- BB_SET_FLAG (b, BB_UPDATE_LIFE);
- changed_here = true;
- }
+ /* If B has a single outgoing edge, but uses a
+ non-trivial jump instruction without side-effects, we
+ can either delete the jump entirely, or replace it
+ with a simple unconditional jump. Use
+ redirect_edge_and_branch to do the dirty work. */
+ if (b->succ
+ && ! b->succ->succ_next
+ && b->succ->dest != EXIT_BLOCK_PTR
+ && onlyjump_p (b->end)
+ && redirect_edge_and_branch (b->succ, b->succ->dest))
+ {
+ BB_SET_FLAG (b, BB_UPDATE_LIFE);
+ update_forwarder_flag (b);
+ changed_here = true;
+ }
- /* If B has a single outgoing edge, but uses a non-trivial jump
- instruction without side-effects, we can either delete the
- jump entirely, or replace it with a simple unconditional jump.
- Use redirect_edge_and_branch to do the dirty work. */
- if (b->succ
- && ! b->succ->succ_next
- && b->succ->dest != EXIT_BLOCK_PTR
- && onlyjump_p (b->end)
- && redirect_edge_and_branch (b->succ, b->succ->dest))
- {
- BB_SET_FLAG (b, BB_UPDATE_LIFE);
- update_forwarder_flag (b);
- changed_here = true;
- }
+ /* Simplify branch to branch. */
+ if (try_forward_edges (mode, b))
+ changed_here = true;
- /* Simplify branch to branch. */
- if (try_forward_edges (mode, b))
- changed_here = true;
+ /* Look for shared code between blocks. */
+ if ((mode & CLEANUP_CROSSJUMP)
+ && try_crossjump_bb (mode, b))
+ changed_here = true;
- /* Look for shared code between blocks. */
- if ((mode & CLEANUP_CROSSJUMP)
- && try_crossjump_bb (mode, b))
- changed_here = true;
+ /* Don't get confused by the index shift caused by
+ deleting blocks. */
+ if (!changed_here)
+ i = b->index + 1;
+ else
+ changed = true;
+ }
- /* Don't get confused by the index shift caused by deleting
- blocks. */
- if (!changed_here)
- i = b->index + 1;
- else
+ if ((mode & CLEANUP_CROSSJUMP)
+ && try_crossjump_bb (mode, EXIT_BLOCK_PTR))
changed = true;
- }
-
- if ((mode & CLEANUP_CROSSJUMP)
- && try_crossjump_bb (mode, EXIT_BLOCK_PTR))
- changed = true;
#ifdef ENABLE_CHECKING
- if (changed)
- verify_flow_info ();
+ if (changed)
+ verify_flow_info ();
#endif
- changed_overall |= changed;
+ changed_overall |= changed;
+ }
+ while (changed);
}
- while (changed);
if (mode & CLEANUP_CROSSJUMP)
remove_fake_edges ();
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index ff25523..3cb5c68 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -8616,3 +8616,18 @@ object files that are not referenced from @code{main} and uses export
lists.
@end table
+
+@deftypefn {Target Hook} bool TARGET_CANNOT_MODIFY_JUMPS_P (void)
+This target hook returns @code{true} past the point in which new jump
+instructions could be created. On machines that require a register for
+every jump such as the SHmedia ISA of SH5, this point would typically be
+reload, so this target hook should be defined to a function such as:
+
+@smallexample
+static bool
+cannot_modify_jumps_past_reload_p ()
+@{
+ return (reload_completed || reload_in_progress);
+@}
+@end smallexample
+@end deftypefn
diff --git a/gcc/hooks.c b/gcc/hooks.c
new file mode 100644
index 0000000..387f4db
--- /dev/null
+++ b/gcc/hooks.c
@@ -0,0 +1,34 @@
+/* General-purpose hooks.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This program 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.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+/* This file contains generic hooks that can be used as defaults for
+ target or language-dependent hook initializers. */
+
+#include "config.h"
+#include "system.h"
+#include "hooks.h"
+
+/* Generic hook that takes no arguments and returns false. */
+bool
+hook_void_bool_false ()
+{
+ return false;
+}
diff --git a/gcc/hooks.h b/gcc/hooks.h
new file mode 100644
index 0000000..7a8daa5
--- /dev/null
+++ b/gcc/hooks.h
@@ -0,0 +1,22 @@
+/* General-purpose hooks.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This program 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.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+bool hook_void_bool_false PARAMS ((void));
diff --git a/gcc/target-def.h b/gcc/target-def.h
index bc93b50..71987f5 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -175,6 +175,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TARGET_SECTION_TYPE_FLAGS default_section_type_flags
#endif
+/* In hook.c. */
+#define TARGET_CANNOT_MODIFY_JUMPS_P hook_void_bool_false
+
/* The whole shebang. */
#define TARGET_INITIALIZER \
{ \
@@ -192,5 +195,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_EXPAND_BUILTIN, \
TARGET_SECTION_TYPE_FLAGS, \
TARGET_HAVE_NAMED_SECTIONS, \
- TARGET_HAVE_CTORS_DTORS \
+ TARGET_HAVE_CTORS_DTORS, \
+ TARGET_CANNOT_MODIFY_JUMPS_P \
}
+
+#include "hooks.h"
diff --git a/gcc/target.h b/gcc/target.h
index 38ce359..5ee9aa6 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -184,6 +184,10 @@ struct gcc_target
/* True if "native" constructors and destructors are supported,
false if we're using collect2 for the job. */
bool have_ctors_dtors;
+
+ /* True if new jumps cannot be created, to replace existing ones or
+ not, at the current point in the compilation. */
+ bool (* cannot_modify_jumps_p) PARAMS ((void));
};
extern struct gcc_target targetm;