OSDN Git Service

PR debug/41276
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfg.c
index 3b99d6c..02daee0 100644 (file)
@@ -1354,6 +1354,24 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b)
       && DECL_NONLOCAL (gimple_label_label (stmt)))
     return false;
 
+  /* Examine the labels at the beginning of B.  */
+  for (gsi = gsi_start_bb (b); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      tree lab;
+      stmt = gsi_stmt (gsi);
+      if (gimple_code (stmt) != GIMPLE_LABEL)
+       break;
+      lab = gimple_label_label (stmt);
+
+      /* Do not remove user labels.  */
+      if (!DECL_ARTIFICIAL (lab))
+       return false;
+    }
+
+  /* Protect the loop latches.  */
+  if (current_loops && b->loop_father->latch == b)
+    return false;
+
   /* It must be possible to eliminate all phi nodes in B.  If ssa form
      is not up-to-date, we cannot eliminate any phis; however, if only
      some symbols as whole are marked for renaming, this is not a problem,
@@ -1377,24 +1395,52 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b)
        }
     }
 
-  /* Do not remove user labels.  */
-  for (gsi = gsi_start_bb (b); !gsi_end_p (gsi); gsi_next (&gsi))
-    {
-      stmt = gsi_stmt (gsi);
-      if (gimple_code (stmt) != GIMPLE_LABEL)
-       break;
-      if (!DECL_ARTIFICIAL (gimple_label_label (stmt)))
-       return false;
-    }
+  return true;
+}
 
-  /* Protect the loop latches.  */
-  if (current_loops
-      && b->loop_father->latch == b)
-    return false;
+/* Return true if the var whose chain of uses starts at PTR has no
+   nondebug uses.  */
+bool
+has_zero_uses_1 (const ssa_use_operand_t *head)
+{
+  const ssa_use_operand_t *ptr;
+
+  for (ptr = head->next; ptr != head; ptr = ptr->next)
+    if (!is_gimple_debug (USE_STMT (ptr)))
+      return false;
 
   return true;
 }
 
+/* Return true if the var whose chain of uses starts at PTR has a
+   single nondebug use.  Set USE_P and STMT to that single nondebug
+   use, if so, or to NULL otherwise.  */
+bool
+single_imm_use_1 (const ssa_use_operand_t *head,
+                 use_operand_p *use_p, gimple *stmt)
+{
+  ssa_use_operand_t *ptr, *single_use = 0;
+
+  for (ptr = head->next; ptr != head; ptr = ptr->next)
+    if (!is_gimple_debug (USE_STMT (ptr)))
+      {
+       if (single_use)
+         {
+           single_use = NULL;
+           break;
+         }
+       single_use = ptr;
+      }
+
+  if (use_p)
+    *use_p = single_use;
+
+  if (stmt)
+    *stmt = single_use ? single_use->loc.stmt : NULL;
+
+  return !!single_use;
+}
+
 /* Replaces all uses of NAME by VAL.  */
 
 void
@@ -2263,7 +2309,11 @@ remove_bb (basic_block bb)
   /* Remove all the instructions in the block.  */
   if (bb_seq (bb) != NULL)
     {
-      for (i = gsi_start_bb (bb); !gsi_end_p (i);)
+      /* Walk backwards so as to get a chance to substitute all
+        released DEFs into debug stmts.  See
+        eliminate_unnecessary_stmts() in tree-ssa-dce.c for more
+        details.  */
+      for (i = gsi_last_bb (bb); !gsi_end_p (i);)
        {
          gimple stmt = gsi_stmt (i);
          if (gimple_code (stmt) == GIMPLE_LABEL
@@ -2299,13 +2349,17 @@ remove_bb (basic_block bb)
              gsi_remove (&i, true);
            }
 
+         if (gsi_end_p (i))
+           i = gsi_last_bb (bb);
+         else
+           gsi_prev (&i);
+
          /* Don't warn for removed gotos.  Gotos are often removed due to
             jump threading, thus resulting in bogus warnings.  Not great,
             since this way we lose warnings for gotos in the original
             program that are indeed unreachable.  */
          if (gimple_code (stmt) != GIMPLE_GOTO
-             && gimple_has_location (stmt)
-             && !loc)
+             && gimple_has_location (stmt))
            loc = gimple_location (stmt);
        }
     }
@@ -2681,11 +2735,17 @@ gimple_cfg2vcg (FILE *file)
 bool
 is_ctrl_stmt (gimple t)
 {
-  return gimple_code (t) == GIMPLE_COND
-    || gimple_code (t) == GIMPLE_SWITCH
-    || gimple_code (t) == GIMPLE_GOTO
-    || gimple_code (t) == GIMPLE_RETURN
-    || gimple_code (t) == GIMPLE_RESX;
+  switch (gimple_code (t))
+    {
+    case GIMPLE_COND:
+    case GIMPLE_SWITCH:
+    case GIMPLE_GOTO:
+    case GIMPLE_RETURN:
+    case GIMPLE_RESX:
+      return true;
+    default:
+      return false;
+    }
 }
 
 
@@ -2697,24 +2757,30 @@ is_ctrl_altering_stmt (gimple t)
 {
   gcc_assert (t);
 
-  if (is_gimple_call (t))
+  switch (gimple_code (t))
     {
-      int flags = gimple_call_flags (t);
+    case GIMPLE_CALL:
+      {
+       int flags = gimple_call_flags (t);
 
-      /* A non-pure/const call alters flow control if the current
-        function has nonlocal labels.  */
-      if (!(flags & (ECF_CONST | ECF_PURE))
-         && cfun->has_nonlocal_label)
-       return true;
+       /* A non-pure/const call alters flow control if the current
+          function has nonlocal labels.  */
+       if (!(flags & (ECF_CONST | ECF_PURE)) && cfun->has_nonlocal_label)
+         return true;
 
-      /* A call also alters control flow if it does not return.  */
-      if (gimple_call_flags (t) & ECF_NORETURN)
-       return true;
-    }
+       /* A call also alters control flow if it does not return.  */
+       if (gimple_call_flags (t) & ECF_NORETURN)
+         return true;
+      }
+      break;
 
-  /* OpenMP directives alter control flow.  */
-  if (is_gimple_omp (t))
-    return true;
+    CASE_GIMPLE_OMP:
+      /* OpenMP directives alter control flow.  */
+      return true;
+
+    default:
+      break;
+    }
 
   /* If a statement can throw, it alters control flow.  */
   return stmt_can_throw_internal (t);
@@ -2807,7 +2873,14 @@ gimple
 first_stmt (basic_block bb)
 {
   gimple_stmt_iterator i = gsi_start_bb (bb);
-  return !gsi_end_p (i) ? gsi_stmt (i) : NULL;
+  gimple stmt = NULL;
+
+  while (!gsi_end_p (i) && is_gimple_debug ((stmt = gsi_stmt (i))))
+    {
+      gsi_next (&i);
+      stmt = NULL;
+    }
+  return stmt;
 }
 
 /* Return the first non-label statement in basic block BB.  */
@@ -2826,8 +2899,15 @@ first_non_label_stmt (basic_block bb)
 gimple
 last_stmt (basic_block bb)
 {
-  gimple_stmt_iterator b = gsi_last_bb (bb);
-  return !gsi_end_p (b) ? gsi_stmt (b) : NULL;
+  gimple_stmt_iterator i = gsi_last_bb (bb);
+  gimple stmt = NULL;
+
+  while (!gsi_end_p (i) && is_gimple_debug ((stmt = gsi_stmt (i))))
+    {
+      gsi_prev (&i);
+      stmt = NULL;
+    }
+  return stmt;
 }
 
 /* Return the last statement of an otherwise empty block.  Return NULL
@@ -2837,14 +2917,14 @@ last_stmt (basic_block bb)
 gimple
 last_and_only_stmt (basic_block bb)
 {
-  gimple_stmt_iterator i = gsi_last_bb (bb);
+  gimple_stmt_iterator i = gsi_last_nondebug_bb (bb);
   gimple last, prev;
 
   if (gsi_end_p (i))
     return NULL;
 
   last = gsi_stmt (i);
-  gsi_prev (&i);
+  gsi_prev_nondebug (&i);
   if (gsi_end_p (i))
     return last;
 
@@ -2901,11 +2981,15 @@ static basic_block
 split_edge_bb_loc (edge edge_in)
 {
   basic_block dest = edge_in->dest;
+  basic_block dest_prev = dest->prev_bb;
 
-  if (dest->prev_bb && find_edge (dest->prev_bb, dest))
-    return edge_in->src;
-  else
-    return dest->prev_bb;
+  if (dest_prev)
+    {
+      edge e = find_edge (dest_prev, dest);
+      if (e && !(e->flags & EDGE_COMPLEX))
+       return edge_in->src;
+    }
+  return dest_prev;
 }
 
 /* Split a (typically critical) edge EDGE_IN.  Return the new block.
@@ -3889,12 +3973,13 @@ verify_gimple_assign_single (gimple stmt)
            return true;
          }
 
-       if (!one_pointer_to_useless_type_conversion_p (lhs_type,
-                                                      TREE_TYPE (op)))
+       if (!types_compatible_p (TREE_TYPE (op), TREE_TYPE (TREE_TYPE (rhs1)))
+           && !one_pointer_to_useless_type_conversion_p (TREE_TYPE (rhs1),
+                                                         TREE_TYPE (op)))
          {
            error ("type mismatch in address expression");
-           debug_generic_stmt (lhs_type);
-           debug_generic_stmt (TYPE_POINTER_TO (TREE_TYPE (op)));
+           debug_generic_stmt (TREE_TYPE (rhs1));
+           debug_generic_stmt (TREE_TYPE (op));
            return true;
          }
 
@@ -4077,7 +4162,7 @@ verify_gimple_phi (gimple stmt)
   tree type = TREE_TYPE (gimple_phi_result (stmt));
   unsigned i;
 
-  if (!is_gimple_variable (gimple_phi_result (stmt)))
+  if (TREE_CODE (gimple_phi_result (stmt)) != SSA_NAME)
     {
       error ("Invalid PHI result");
       return true;
@@ -4108,23 +4193,28 @@ verify_gimple_phi (gimple stmt)
 }
 
 
+/* Verify a gimple debug statement STMT.
+   Returns true if anything is wrong.  */
+
+static bool
+verify_gimple_debug (gimple stmt ATTRIBUTE_UNUSED)
+{
+  /* There isn't much that could be wrong in a gimple debug stmt.  A
+     gimple debug bind stmt, for example, maps a tree, that's usually
+     a VAR_DECL or a PARM_DECL, but that could also be some scalarized
+     component or member of an aggregate type, to another tree, that
+     can be an arbitrary expression.  These stmts expand into debug
+     insns, and are converted to debug notes by var-tracking.c.  */
+  return false;
+}
+
+
 /* Verify the GIMPLE statement STMT.  Returns true if there is an
    error, otherwise false.  */
 
 static bool
 verify_types_in_gimple_stmt (gimple stmt)
 {
-  if (is_gimple_omp (stmt))
-    {
-      /* OpenMP directives are validated by the FE and never operated
-        on by the optimizers.  Furthermore, GIMPLE_OMP_FOR may contain
-        non-gimple expressions when the main index variable has had
-        its address taken.  This does not affect the loop itself
-        because the header of an GIMPLE_OMP_FOR is merely used to determine
-        how to setup the parallel iteration.  */
-      return false;
-    }
-
   switch (gimple_code (stmt))
     {
     case GIMPLE_ASSIGN:
@@ -4162,6 +4252,18 @@ verify_types_in_gimple_stmt (gimple stmt)
     case GIMPLE_PREDICT:
       return false;
 
+    CASE_GIMPLE_OMP:
+      /* OpenMP directives are validated by the FE and never operated
+        on by the optimizers.  Furthermore, GIMPLE_OMP_FOR may contain
+        non-gimple expressions when the main index variable has had
+        its address taken.  This does not affect the loop itself
+        because the header of an GIMPLE_OMP_FOR is merely used to determine
+        how to setup the parallel iteration.  */
+      return false;
+
+    case GIMPLE_DEBUG:
+      return verify_gimple_debug (stmt);
+
     default:
       gcc_unreachable ();
     }
@@ -4268,6 +4370,9 @@ verify_stmt (gimple_stmt_iterator *gsi)
        }
     }
 
+  if (is_gimple_debug (stmt))
+    return false;
+
   memset (&wi, 0, sizeof (wi));
   addr = walk_gimple_op (gsi_stmt (*gsi), verify_expr, &wi);
   if (addr)
@@ -4940,16 +5045,19 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
   if (e->flags & EDGE_ABNORMAL)
     return NULL;
 
-  if (e->src != ENTRY_BLOCK_PTR
-      && (ret = gimple_try_redirect_by_replacing_jump (e, dest)))
-    return ret;
-
   if (e->dest == dest)
     return NULL;
 
   if (e->flags & EDGE_EH)
     return redirect_eh_edge (e, dest);
 
+  if (e->src != ENTRY_BLOCK_PTR)
+    {
+      ret = gimple_try_redirect_by_replacing_jump (e, dest);
+      if (ret)
+       return ret;
+    }
+
   gsi = gsi_last_bb (bb);
   stmt = gsi_end_p (gsi) ? NULL : gsi_stmt (gsi);
 
@@ -6334,7 +6442,7 @@ dump_function_to_file (tree fn, FILE *file, int flags)
     print_node (file, "", fn, 2);
 
   dsf = DECL_STRUCT_FUNCTION (fn);
-  if (dsf && (flags & TDF_DETAILS))
+  if (dsf && (flags & TDF_EH))
     dump_eh_tree (file, dsf);
 
   if (flags & TDF_RAW && !gimple_has_body_p (fn))
@@ -6617,7 +6725,7 @@ debug_loop_num (unsigned num, int verbosity)
 static bool
 gimple_block_ends_with_call_p (basic_block bb)
 {
-  gimple_stmt_iterator gsi = gsi_last_bb (bb);
+  gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
   return is_gimple_call (gsi_stmt (gsi));
 }
 
@@ -6923,8 +7031,12 @@ remove_edge_and_dominated_blocks (edge e)
     remove_edge (e);
   else
     {
-      for (i = 0; VEC_iterate (basic_block, bbs_to_remove, i, bb); i++)
-       delete_basic_block (bb);
+      /* Walk backwards so as to get a chance to substitute all
+        released DEFs into debug stmts.  See
+        eliminate_unnecessary_stmts() in tree-ssa-dce.c for more
+        details.  */
+      for (i = VEC_length (basic_block, bbs_to_remove); i-- > 0; )
+       delete_basic_block (VEC_index (basic_block, bbs_to_remove, i));
     }
 
   /* Update the dominance information.  The immediate dominator may change only
@@ -7154,7 +7266,7 @@ split_critical_edges (void)
             Go ahead and split them too.  This matches the logic in
             gimple_find_edge_insert_loc.  */
          else if ((!single_pred_p (e->dest)
-                   || phi_nodes (e->dest)
+                   || !gimple_seq_empty_p (phi_nodes (e->dest))
                    || e->dest == EXIT_BLOCK_PTR)
                   && e->src != ENTRY_BLOCK_PTR
                   && !(e->flags & EDGE_ABNORMAL))