OSDN Git Service

* Makefile.in (cfgrtl.o): Add expr.h dependency.
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 26 Jun 2003 06:13:27 +0000 (06:13 +0000)
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 26 Jun 2003 06:13:27 +0000 (06:13 +0000)
* cfgrtl.c: Include expr.h.
(mark_killed_regs, safe_insert_insn_on_edge): New
functions.
* config/i386/i386.h (AVOID_CCMODE_COPIES): Define.
* basic-block.h (safe_insert_insn_on_edge): Declare.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@68518 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/basic-block.h
gcc/cfgrtl.c
gcc/config/i386/i386.h

index a27835d..07d016c 100644 (file)
@@ -1,3 +1,12 @@
+2003-06-24  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
+
+       * Makefile.in (cfgrtl.o): Add expr.h dependency.
+       * cfgrtl.c: Include expr.h.
+       (mark_killed_regs, safe_insert_insn_on_edge): New
+       functions.
+       * config/i386/i386.h (AVOID_CCMODE_COPIES): Define.
+       * basic-block.h (safe_insert_insn_on_edge): Declare.
+
 2003-06-26  Neil Booth  <neil@daikokuya.co.uk>
 
        * c-opts.c (missing_arg): Make non-static.
index a3cc5df..5029c52 100644 (file)
@@ -1659,7 +1659,7 @@ cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TR
    $(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
+   function.h except.h $(GGC_H) $(TM_P_H) insn-config.h $(EXPR_H)
 cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(BASIC_BLOCK_H) hard-reg-set.h insn-config.h $(RECOG_H) $(GGC_H) $(TM_P_H)
 cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
index 40775b9..b26b143 100644 (file)
@@ -340,6 +340,7 @@ extern void update_bb_for_insn              PARAMS ((basic_block));
 extern void free_basic_block_vars      PARAMS ((int));
 
 extern void insert_insn_on_edge                PARAMS ((rtx, edge));
+bool safe_insert_insn_on_edge (rtx, edge);
 
 extern void commit_edge_insertions     PARAMS ((void));
 extern void commit_edge_insertions_watch_calls PARAMS ((void));
index 569a604..a08d29f 100644 (file)
@@ -56,6 +56,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "obstack.h"
 #include "insn-config.h"
 #include "cfglayout.h"
+#include "expr.h"
 
 /* Stubs in case we don't have a return insn.  */
 #ifndef HAVE_return
@@ -88,6 +89,7 @@ static bool rtl_redirect_edge_and_branch (edge, basic_block);
 static edge rtl_split_block (basic_block, void *);
 static void rtl_dump_bb (basic_block, FILE *);
 static int rtl_verify_flow_info_1 (void);
+static void mark_killed_regs (rtx, rtx, void *);
 \f
 /* Return true if NOTE is not one of the ones that must be kept paired,
    so that we may simply delete it.  */
@@ -1305,6 +1307,101 @@ insert_insn_on_edge (rtx pattern, edge e)
   end_sequence ();
 }
 
+/* Called from safe_insert_insn_on_edge through note_stores, marks live
+   registers that are killed by the store.  */
+static void
+mark_killed_regs (rtx reg, rtx set ATTRIBUTE_UNUSED, void *data)
+{
+  regset killed = data;
+  int regno, i;
+
+  if (GET_CODE (reg) == SUBREG)
+    reg = SUBREG_REG (reg);
+  if (!REG_P (reg))
+    return;
+  regno = REGNO (reg);
+  if (regno >= FIRST_PSEUDO_REGISTER)
+    SET_REGNO_REG_SET (killed, regno);
+  else
+    {
+      for (i = 0; i < HARD_REGNO_NREGS (regno, GET_MODE (reg)); i++)
+       SET_REGNO_REG_SET (killed, regno + i);
+    }
+}
+
+/* Similar to insert_insn_on_edge, tries to put INSN to edge E.  Additionally
+   it checks whether this will not clobber the registers that are live on the
+   edge (i.e. it requieres liveness information to be up-to-date) and if there
+   are some, then it tries to save and restore them.  Returns true if
+   succesful.  */
+bool
+safe_insert_insn_on_edge (rtx insn, edge e)
+{
+  rtx x;
+  regset_head killed_head;
+  regset killed = INITIALIZE_REG_SET (killed_head);
+  rtx save_regs = NULL_RTX;
+  int regno, noccmode;
+  enum machine_mode mode;
+
+#ifdef AVOID_CCMODE_COPIES
+  noccmode = true;
+#else
+  noccmode = false;
+#endif
+
+  for (x = insn; x; x = NEXT_INSN (x))
+    if (INSN_P (x))
+      note_stores (PATTERN (x), mark_killed_regs, killed);
+  bitmap_operation (killed, killed, e->dest->global_live_at_start,
+                   BITMAP_AND);
+
+  EXECUTE_IF_SET_IN_REG_SET (killed, 0, regno,
+    {
+      mode = regno < FIRST_PSEUDO_REGISTER
+             ? reg_raw_mode[regno]
+             : GET_MODE (regno_reg_rtx[regno]);
+      if (mode == VOIDmode)
+       return false;
+
+      if (noccmode && mode == CCmode)
+       return false;
+       
+      save_regs = alloc_EXPR_LIST (0,
+                                  alloc_EXPR_LIST (0,
+                                                   gen_reg_rtx (mode),
+                                                   gen_raw_REG (mode, regno)),
+                                  save_regs);
+    });
+
+  if (save_regs)
+    {
+      rtx from, to;
+
+      start_sequence ();
+      for (x = save_regs; x; x = XEXP (x, 1))
+       {
+         from = XEXP (XEXP (x, 0), 1);
+         to = XEXP (XEXP (x, 0), 0);
+         emit_move_insn (to, from);
+       }
+      emit_insn (insn);
+      for (x = save_regs; x; x = XEXP (x, 1))
+       {
+         from = XEXP (XEXP (x, 0), 0);
+         to = XEXP (XEXP (x, 0), 1);
+         emit_move_insn (to, from);
+       }
+      insn = get_insns ();
+      end_sequence ();
+      free_EXPR_LIST_list (&save_regs);
+    }
+  insert_insn_on_edge (insn, e);
+  
+  FREE_REG_SET (killed);
+  return true;
+}
+
 /* Update the CFG for the instructions queued on edge E.  */
 
 static void
index 5f390f0..c115f6a 100644 (file)
@@ -1123,6 +1123,9 @@ do {                                                                      \
               && (TARGET_64BIT || !TARGET_PARTIAL_REG_STALL))  \
           || ((MODE2) == DImode && TARGET_64BIT))))
 
+/* It is possible to write patterns to move flags; but until someone
+   does it,  */
+#define AVOID_CCMODE_COPIES
 
 /* Specify the modes required to caller save a given hard regno.
    We do this on i386 to prevent flags from being saved at all.