hooks.c: New file.
authorAlexandre Oliva <aoliva@redhat.com>
Sat, 9 Feb 2002 02:18:12 +0000 (02:18 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Sat, 9 Feb 2002 02:18:12 +0000 (02:18 +0000)
* 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

gcc/ChangeLog
gcc/Makefile.in
gcc/bb-reorder.c
gcc/cfgcleanup.c
gcc/doc/tm.texi
gcc/hooks.c [new file with mode: 0644]
gcc/hooks.h [new file with mode: 0644]
gcc/target-def.h
gcc/target.h

index 7ce74962c71b809b77f5a927961904bb6636ccc0..7c2267c670c4081bd46e996808b4cbfd4b3e244b 100644 (file)
@@ -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):
index f21ed3df33da191a87ef151597f971f033f33dfa..59f1d3aff3de1a23e8feba7620c4a82b9bb0a415 100644 (file)
@@ -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 \
index 97ad1426b369fc12c441169666864fd72e245270..2578604889ec59ca76be6d57b19c7b0db0b67b43 100644 (file)
@@ -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 ();
index 13c5a8e1352bbc71b8f8f60863de42dc0997f408..d9f9cf261e5c10afbe7dcfabd6a22d1b1f9b4f0b 100644 (file)
@@ -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 ();
index ff255238da4786f497d61a26f5baa9cdabc76b54..3cb5c68c5faf9430bd4b1cc9569240c6336d7b10 100644 (file)
@@ -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 (file)
index 0000000..387f4db
--- /dev/null
@@ -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 (file)
index 0000000..7a8daa5
--- /dev/null
@@ -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));
index bc93b507f7e935752aa8b3a6b0ac95bf5d0bdd3c..71987f5caf6b30474c2395ed056f3e59ddcf0bb9 100644 (file)
@@ -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"
index 38ce359eea2fc7cdcc29900bc4a71ac5b1e68af6..5ee9aa64d57746a499e5f47d334d2244120c4223 100644 (file)
@@ -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;