OSDN Git Service

2006-05-15 Mircea Namolaru <namolaru@il.ibm.com>
[pf3gnuchains/gcc-fork.git] / gcc / mode-switching.c
index 968061c..0d485dd 100644 (file)
@@ -16,8 +16,8 @@ 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.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -34,6 +34,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "output.h"
 #include "tm_p.h"
 #include "function.h"
+#include "tree-pass.h"
+#include "timevar.h"
 
 /* We want target macros for the mode switching code to be able to refer
    to instruction attribute values.  */
@@ -102,7 +104,7 @@ static struct seginfo *
 new_seginfo (int mode, rtx insn, int bb, HARD_REG_SET regs_live)
 {
   struct seginfo *ptr;
-  ptr = xmalloc (sizeof (struct seginfo));
+  ptr = XNEW (struct seginfo);
   ptr->mode = mode;
   ptr->insn_ptr = insn;
   ptr->bbnum = bb;
@@ -380,8 +382,8 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
 /* Find all insns that need a particular mode setting, and insert the
    necessary mode switches.  Return true if we did work.  */
 
-int
-optimize_mode_switching (FILE *file)
+static int
+optimize_mode_switching (void)
 {
   rtx insn;
   int e;
@@ -413,7 +415,7 @@ optimize_mode_switching (FILE *file)
        entry_exit_extra = 3;
 #endif
        bb_info[n_entities]
-         = xcalloc (last_basic_block + entry_exit_extra, sizeof **bb_info);
+         = XCNEWVEC (struct bb_info, last_basic_block + entry_exit_extra);
        entity_map[n_entities++] = e;
        if (num_modes[e] > max_num_modes)
          max_num_modes = num_modes[e];
@@ -454,6 +456,18 @@ optimize_mode_switching (FILE *file)
 
          REG_SET_TO_HARD_REG_SET (live_now,
                                   bb->il.rtl->global_live_at_start);
+
+         /* Pretend the mode is clobbered across abnormal edges.  */
+         {
+           edge_iterator ei;
+           edge e;
+           FOR_EACH_EDGE (e, ei, bb->preds)
+             if (e->flags & EDGE_COMPLEX)
+               break;
+           if (e)
+             RESET_BIT (transp[bb->index], j);
+         }
+
          for (insn = BB_HEAD (bb);
               insn != NULL && insn != NEXT_INSN (BB_END (bb));
               insn = NEXT_INSN (insn))
@@ -549,7 +563,7 @@ optimize_mode_switching (FILE *file)
 
       FOR_EACH_BB (bb)
        sbitmap_not (kill[bb->index], transp[bb->index]);
-      edge_list = pre_edge_lcm (file, n_entities, transp, comp, antic,
+      edge_list = pre_edge_lcm (n_entities, transp, comp, antic,
                                kill, &insert, &delete);
 
       for (j = n_entities - 1; j >= 0; j--)
@@ -708,4 +722,44 @@ optimize_mode_switching (FILE *file)
 
   return 1;
 }
+
+#endif /* OPTIMIZE_MODE_SWITCHING */
+\f
+static bool
+gate_mode_switching (void)
+{
+#ifdef OPTIMIZE_MODE_SWITCHING
+  return true;
+#else
+  return false;
+#endif
+}
+
+static unsigned int
+rest_of_handle_mode_switching (void)
+{
+#ifdef OPTIMIZE_MODE_SWITCHING
+  no_new_pseudos = 0;
+  optimize_mode_switching ();
+  no_new_pseudos = 1;
 #endif /* OPTIMIZE_MODE_SWITCHING */
+  return 0;
+}
+
+
+struct tree_opt_pass pass_mode_switching =
+{
+  "mode-sw",                            /* name */
+  gate_mode_switching,                  /* gate */
+  rest_of_handle_mode_switching,        /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_MODE_SWITCH,                       /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func,                       /* todo_flags_finish */
+  0                                     /* letter */
+};