OSDN Git Service

* testsuite/lib/libgomp-dg.exp (libgomp_init): Compute multilib-related
[pf3gnuchains/gcc-fork.git] / gcc / regmove.c
index d93c056..1502c08 100644 (file)
@@ -43,6 +43,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "except.h"
 #include "toplev.h"
 #include "reload.h"
+#include "timevar.h"
+#include "tree-pass.h"
 
 
 /* Turn STACK_GROWS_DOWNWARD into a boolean.  */
@@ -74,12 +76,12 @@ static void flags_set_1 (rtx, rtx, void *);
 static int try_auto_increment (rtx, rtx, rtx, rtx, HOST_WIDE_INT, int);
 static int find_matches (rtx, struct match *);
 static void replace_in_call_usage (rtx *, unsigned int, rtx, rtx);
-static int fixup_match_1 (rtx, rtx, rtx, rtx, rtx, int, int, int, FILE *);
+static int fixup_match_1 (rtx, rtx, rtx, rtx, rtx, int, int, int);
 static int reg_is_remote_constant_p (rtx, rtx, rtx);
 static int stable_and_no_regs_but_for_p (rtx, rtx, rtx);
 static int regclass_compatible_p (int, int);
 static int replacement_quality (rtx);
-static int fixup_match_2 (rtx, rtx, rtx, rtx, FILE *);
+static int fixup_match_2 (rtx, rtx, rtx, rtx);
 
 /* Return nonzero if registers with CLASS1 and CLASS2 can be merged without
    causing too much register allocation problems.  */
@@ -857,13 +859,13 @@ reg_is_remote_constant_p (rtx reg, rtx insn, rtx first)
     return 0;
 
   /* Look for the set.  */
-  for (p = LOG_LINKS (insn); p; p = XEXP (p, 1))
+  for (p = BB_HEAD (BLOCK_FOR_INSN (insn)); p != insn; p = NEXT_INSN (p))
     {
       rtx s;
 
-      if (REG_NOTE_KIND (p) != 0)
+      if (!INSN_P (p))
        continue;
-      s = single_set (XEXP (p, 0));
+      s = single_set (p);
       if (s != 0
          && REG_P (SET_DEST (s))
          && REGNO (SET_DEST (s)) == REGNO (reg))
@@ -914,7 +916,7 @@ reg_is_remote_constant_p (rtx reg, rtx insn, rtx first)
    hard register as ultimate source, like the frame pointer.  */
 
 static int
-fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset, FILE *regmove_dump_file)
+fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset)
 {
   rtx p, dst_death = 0;
   int length, num_calls = 0;
@@ -963,8 +965,8 @@ fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset, FILE *regmove_dump_file)
                  REG_N_CALLS_CROSSED (REGNO (dst)) += num_calls;
                }
 
-             if (regmove_dump_file)
-               fprintf (regmove_dump_file,
+             if (dump_file)
+               fprintf (dump_file,
                         "Fixed operand of insn %d.\n",
                          INSN_UID (insn));
 
@@ -1035,8 +1037,8 @@ fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset, FILE *regmove_dump_file)
    REGMOVE_DUMP_FILE is a stream for output of a trace of actions taken
    (or 0 if none should be output).  */
 
-void
-regmove_optimize (rtx f, int nregs, FILE *regmove_dump_file)
+static void
+regmove_optimize (rtx f, int nregs)
 {
   int old_max_uid = get_max_uid ();
   rtx insn;
@@ -1055,10 +1057,10 @@ regmove_optimize (rtx f, int nregs, FILE *regmove_dump_file)
      can suppress some optimizations in those zones.  */
   mark_flags_life_zones (discover_flags_reg ());
 
-  regno_src_regno = xmalloc (sizeof *regno_src_regno * nregs);
+  regno_src_regno = XNEWVEC (int, nregs);
   for (i = nregs; --i >= 0; ) regno_src_regno[i] = -1;
 
-  regmove_bb_head = xmalloc (sizeof (int) * (old_max_uid + 1));
+  regmove_bb_head = XNEWVEC (int, old_max_uid + 1);
   for (i = old_max_uid; i >= 0; i--) regmove_bb_head[i] = -1;
   FOR_EACH_BB (bb)
     regmove_bb_head[INSN_UID (BB_HEAD (bb))] = bb->index;
@@ -1070,8 +1072,8 @@ regmove_optimize (rtx f, int nregs, FILE *regmove_dump_file)
       if (! flag_regmove && pass >= flag_expensive_optimizations)
        goto done;
 
-      if (regmove_dump_file)
-       fprintf (regmove_dump_file, "Starting %s pass...\n",
+      if (dump_file)
+       fprintf (dump_file, "Starting %s pass...\n",
                 pass ? "backward" : "forward");
 
       for (insn = pass ? get_last_insn () : f; insn;
@@ -1207,8 +1209,7 @@ regmove_optimize (rtx f, int nregs, FILE *regmove_dump_file)
                continue;
 
              if (fixup_match_1 (insn, set, src, src_subreg, dst, pass,
-                                op_no, match_no,
-                                regmove_dump_file))
+                                op_no, match_no))
                break;
            }
        }
@@ -1216,8 +1217,8 @@ regmove_optimize (rtx f, int nregs, FILE *regmove_dump_file)
 
   /* A backward pass.  Replace input operands with output operands.  */
 
-  if (regmove_dump_file)
-    fprintf (regmove_dump_file, "Starting backward pass...\n");
+  if (dump_file)
+    fprintf (dump_file, "Starting backward pass...\n");
 
   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
     {
@@ -1306,8 +1307,7 @@ regmove_optimize (rtx f, int nregs, FILE *regmove_dump_file)
                      && GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT
                      && XEXP (SET_SRC (set), 0) == src
                      && fixup_match_2 (insn, dst, src,
-                                       XEXP (SET_SRC (set), 1),
-                                       regmove_dump_file))
+                                       XEXP (SET_SRC (set), 1)))
                    break;
                  continue;
                }
@@ -1366,8 +1366,8 @@ regmove_optimize (rtx f, int nregs, FILE *regmove_dump_file)
                }
 
 
-             if (regmove_dump_file)
-               fprintf (regmove_dump_file,
+             if (dump_file)
+               fprintf (dump_file,
                         "Could fix operand %d of insn %d matching operand %d.\n",
                         op_no, INSN_UID (insn), match_no);
 
@@ -1470,8 +1470,8 @@ regmove_optimize (rtx f, int nregs, FILE *regmove_dump_file)
                        REG_LIVE_LENGTH (srcno) = 2;
                    }
 
-                 if (regmove_dump_file)
-                   fprintf (regmove_dump_file,
+                 if (dump_file)
+                   fprintf (dump_file,
                             "Fixed operand %d of insn %d matching operand %d.\n",
                             op_no, INSN_UID (insn), match_no);
 
@@ -1641,8 +1641,7 @@ replace_in_call_usage (rtx *loc, unsigned int dst_reg, rtx src, rtx insn)
 
 static int
 fixup_match_1 (rtx insn, rtx set, rtx src, rtx src_subreg, rtx dst,
-              int backward, int operand_number, int match_number,
-              FILE *regmove_dump_file)
+              int backward, int operand_number, int match_number)
 {
   rtx p;
   rtx post_inc = 0, post_inc_set = 0, search_end = 0;
@@ -1677,8 +1676,8 @@ fixup_match_1 (rtx insn, rtx set, rtx src, rtx src_subreg, rtx dst,
        code = NOTE;
     }
 
-  if (regmove_dump_file)
-    fprintf (regmove_dump_file,
+  if (dump_file)
+    fprintf (dump_file,
             "Could fix operand %d of insn %d matching operand %d.\n",
             operand_number, INSN_UID (insn), match_number);
 
@@ -2018,8 +2017,8 @@ fixup_match_1 (rtx insn, rtx set, rtx src, rtx src_subreg, rtx dst,
       if (REG_LIVE_LENGTH (REGNO (dst)) < 2)
        REG_LIVE_LENGTH (REGNO (dst)) = 2;
     }
-  if (regmove_dump_file)
-    fprintf (regmove_dump_file,
+  if (dump_file)
+    fprintf (dump_file,
             "Fixed operand %d of insn %d matching operand %d.\n",
             operand_number, INSN_UID (insn), match_number);
   return 1;
@@ -2111,7 +2110,7 @@ static int record_stack_memrefs (rtx *, void *);
 
 /* Main entry point for stack adjustment combination.  */
 
-void
+static void
 combine_stack_adjustments (void)
 {
   basic_block bb;
@@ -2195,7 +2194,7 @@ record_one_stack_memref (rtx insn, rtx *mem, struct csa_memlist *next_memlist)
 {
   struct csa_memlist *ml;
 
-  ml = xmalloc (sizeof (*ml));
+  ml = XNEW (struct csa_memlist);
 
   if (XEXP (*mem, 0) == stack_pointer_rtx)
     ml->sp_offset = 0;
@@ -2461,3 +2460,80 @@ combine_stack_adjustments_for_block (basic_block bb)
   if (memlist)
     free_csa_memlist (memlist);
 }
+\f
+static bool
+gate_handle_regmove (void)
+{
+  return (optimize > 0 && flag_regmove);
+}
+
+
+/* Register allocation pre-pass, to reduce number of moves necessary
+   for two-address machines.  */
+static void
+rest_of_handle_regmove (void)
+{
+  regmove_optimize (get_insns (), max_reg_num ());
+  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
+}
+
+struct tree_opt_pass pass_regmove =
+{
+  "regmove",                            /* name */
+  gate_handle_regmove,                  /* gate */
+  rest_of_handle_regmove,               /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_REGMOVE,                           /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func |
+  TODO_ggc_collect,                     /* todo_flags_finish */
+  'N'                                   /* letter */
+};
+
+
+static bool
+gate_handle_stack_adjustments (void)
+{
+  return (optimize > 0);
+}
+
+static void
+rest_of_handle_stack_adjustments (void)
+{
+  life_analysis (PROP_POSTRELOAD);
+  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE
+               | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0));
+
+  /* This is kind of a heuristic.  We need to run combine_stack_adjustments
+     even for machines with possibly nonzero RETURN_POPS_ARGS
+     and ACCUMULATE_OUTGOING_ARGS.  We expect that only ports having
+     push instructions will have popping returns.  */
+#ifndef PUSH_ROUNDING
+  if (!ACCUMULATE_OUTGOING_ARGS)
+#endif
+    combine_stack_adjustments ();
+}
+
+struct tree_opt_pass pass_stack_adjustments =
+{
+  "csa",                                /* name */
+  gate_handle_stack_adjustments,        /* gate */
+  rest_of_handle_stack_adjustments,     /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  0,                                    /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func |
+  TODO_ggc_collect,                     /* todo_flags_finish */
+  0                                     /* letter */
+};
+