OSDN Git Service

dbgcnt name matching bug fix
[pf3gnuchains/gcc-fork.git] / gcc / tree-outof-ssa.c
index 6000a82..4ed8e9f 100644 (file)
@@ -128,6 +128,25 @@ set_location_for_edge (edge e)
     }
 }
 
+/* Emit insns to copy SRC into DEST converting SRC if necessary.  */
+
+static inline rtx
+emit_partition_copy (rtx dest, rtx src, int unsignedsrcp)
+{
+  rtx seq;
+
+  start_sequence ();
+
+  if (GET_MODE (src) != VOIDmode && GET_MODE (src) != GET_MODE (dest))
+    src = convert_to_mode (GET_MODE (dest), src, unsignedsrcp);
+  emit_move_insn (dest, src);
+
+  seq = get_insns ();
+  end_sequence ();
+
+  return seq;
+}
+
 /* Insert a copy instruction from partition SRC to DEST onto edge E.  */
 
 static void
@@ -149,12 +168,10 @@ insert_partition_copy_on_edge (edge e, int dest, int src)
 
   set_location_for_edge (e);
 
-  /* Partition copy between same base variables only, so it's the same mode,
-     hence we can use emit_move_insn.  */
-  start_sequence ();
-  emit_move_insn (SA.partition_to_pseudo[dest], SA.partition_to_pseudo[src]);
-  seq = get_insns ();
-  end_sequence ();
+  seq = emit_partition_copy (SA.partition_to_pseudo[dest],
+                            SA.partition_to_pseudo[src],
+                            TYPE_UNSIGNED (TREE_TYPE (
+                              partition_to_var (SA.map, src))));
 
   insert_insn_on_edge (seq, e);
 }
@@ -184,8 +201,12 @@ insert_value_copy_on_edge (edge e, int dest, tree src)
   start_sequence ();
   mode = GET_MODE (SA.partition_to_pseudo[dest]);
   x = expand_expr (src, SA.partition_to_pseudo[dest], mode, EXPAND_NORMAL);
-  if (GET_MODE (x) != mode)
+  if (GET_MODE (x) != VOIDmode && GET_MODE (x) != mode)
     x = convert_to_mode (mode, x, TYPE_UNSIGNED (TREE_TYPE (src)));
+  if (CONSTANT_P (x) && GET_MODE (x) == VOIDmode
+      && mode != TYPE_MODE (TREE_TYPE (src)))
+    x = convert_modes (mode, TYPE_MODE (TREE_TYPE (src)),
+                         x, TYPE_UNSIGNED (TREE_TYPE (src)));
   if (x != SA.partition_to_pseudo[dest])
     emit_move_insn (SA.partition_to_pseudo[dest], x);
   seq = get_insns ();
@@ -198,7 +219,7 @@ insert_value_copy_on_edge (edge e, int dest, tree src)
    onto edge E.  */
 
 static void
-insert_rtx_to_part_on_edge (edge e, int dest, rtx src)
+insert_rtx_to_part_on_edge (edge e, int dest, rtx src, int unsignedsrcp)
 {
   rtx seq;
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -214,11 +235,9 @@ insert_rtx_to_part_on_edge (edge e, int dest, rtx src)
   gcc_assert (SA.partition_to_pseudo[dest]);
   set_location_for_edge (e);
 
-  start_sequence ();
-  gcc_assert (GET_MODE (src) == GET_MODE (SA.partition_to_pseudo[dest]));
-  emit_move_insn (SA.partition_to_pseudo[dest], src);
-  seq = get_insns ();
-  end_sequence ();
+  seq = emit_partition_copy (SA.partition_to_pseudo[dest],
+                            src,
+                            unsignedsrcp);
 
   insert_insn_on_edge (seq, e);
 }
@@ -243,11 +262,10 @@ insert_part_to_rtx_on_edge (edge e, rtx dest, int src)
   gcc_assert (SA.partition_to_pseudo[src]);
   set_location_for_edge (e);
 
-  start_sequence ();
-  gcc_assert (GET_MODE (dest) == GET_MODE (SA.partition_to_pseudo[src]));
-  emit_move_insn (dest, SA.partition_to_pseudo[src]);
-  seq = get_insns ();
-  end_sequence ();
+  seq = emit_partition_copy (dest,
+                            SA.partition_to_pseudo[src],
+                            TYPE_UNSIGNED (TREE_TYPE (
+                              partition_to_var (SA.map, src))));
 
   insert_insn_on_edge (seq, e);
 }
@@ -522,14 +540,17 @@ elim_create (elim_graph g, int T)
 
   if (elim_unvisited_predecessor (g, T))
     {
-      rtx U = get_temp_reg (partition_to_var (g->map, T));
+      tree var = partition_to_var (g->map, T);
+      rtx U = get_temp_reg (var);
+      int unsignedsrcp = TYPE_UNSIGNED (TREE_TYPE (var));
+
       insert_part_to_rtx_on_edge (g->e, U, T);
       FOR_EACH_ELIM_GRAPH_PRED (g, T, P, 
        {
          if (!TEST_BIT (g->visited, P))
            {
              elim_backward (g, P);
-             insert_rtx_to_part_on_edge (g->e, P, U);
+             insert_rtx_to_part_on_edge (g->e, P, U, unsignedsrcp);
            }
        });
     }
@@ -791,7 +812,7 @@ expand_phi_nodes (struct ssaexpand *sa)
 static void
 remove_ssa_form (bool perform_ter, struct ssaexpand *sa)
 {
-  gimple *values = NULL;
+  bitmap values = NULL;
   var_map map;
   unsigned i;
 
@@ -832,6 +853,67 @@ remove_ssa_form (bool perform_ter, struct ssaexpand *sa)
 }
 
 
+/* If not already done so for basic block BB, assign increasing uids
+   to each of its instructions.  */
+
+static void
+maybe_renumber_stmts_bb (basic_block bb)
+{
+  unsigned i = 0;
+  gimple_stmt_iterator gsi;
+  
+  if (!bb->aux)
+    return;
+  bb->aux = NULL;
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      gimple stmt = gsi_stmt (gsi);
+      gimple_set_uid (stmt, i);
+      i++;
+    }
+}
+
+
+/* Return true if we can determine that the SSA_NAMEs RESULT (a result
+   of a PHI node) and ARG (one of its arguments) conflict.  Return false
+   otherwise, also when we simply aren't sure.  */
+
+static bool
+trivially_conflicts_p (basic_block bb, tree result, tree arg)
+{
+  use_operand_p use;
+  imm_use_iterator imm_iter;
+  gimple defa = SSA_NAME_DEF_STMT (arg);
+
+  /* If ARG isn't defined in the same block it's too complicated for
+     our little mind.  */
+  if (gimple_bb (defa) != bb)
+    return false;
+
+  FOR_EACH_IMM_USE_FAST (use, imm_iter, result)
+    {
+      gimple use_stmt = USE_STMT (use);
+      /* Now, if there's a use of RESULT that lies outside this basic block,
+        then there surely is a conflict with ARG.  */
+      if (gimple_bb (use_stmt) != bb)
+       return true;
+      if (gimple_code (use_stmt) == GIMPLE_PHI)
+       continue;
+      /* The use now is in a real stmt of BB, so if ARG was defined
+         in a PHI node (like RESULT) both conflict.  */
+      if (gimple_code (defa) == GIMPLE_PHI)
+       return true;
+      maybe_renumber_stmts_bb (bb);
+      /* If the use of RESULT occurs after the definition of ARG,
+         the two conflict too.  */
+      if (gimple_uid (defa) < gimple_uid (use_stmt))
+       return true;
+    }
+  
+  return false;
+}
+
+
 /* Search every PHI node for arguments associated with backedges which
    we can trivially determine will need a copy (the argument is either
    not an SSA_NAME or the argument has a different underlying variable
@@ -849,6 +931,9 @@ insert_backedge_copies (void)
 
   FOR_EACH_BB (bb)
     {
+      /* Mark block as possibly needing calculation of UIDs.  */
+      bb->aux = &bb->aux;
+
       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        {
          gimple phi = gsi_stmt (gsi);
@@ -871,7 +956,8 @@ insert_backedge_copies (void)
                 needed.  */
              if ((e->flags & EDGE_DFS_BACK)
                  && (TREE_CODE (arg) != SSA_NAME
-                     || SSA_NAME_VAR (arg) != result_var))
+                     || SSA_NAME_VAR (arg) != result_var
+                     || trivially_conflicts_p (bb, result, arg)))
                {
                  tree name;
                  gimple stmt, last = NULL;
@@ -915,6 +1001,9 @@ insert_backedge_copies (void)
                }
            }
        }
+
+      /* Unmark this block again.  */
+      bb->aux = NULL;
     }
 }
 
@@ -926,7 +1015,7 @@ finish_out_of_ssa (struct ssaexpand *sa)
 {
   free (sa->partition_to_pseudo);
   if (sa->values)
-    free (sa->values);
+    BITMAP_FREE (sa->values);
   delete_var_map (sa->map);
   BITMAP_FREE (sa->partition_has_default_def);
   memset (sa, 0, sizeof *sa);