OSDN Git Service

PR c++/55877
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfg.c
index 7151fa7..d56650d 100644 (file)
@@ -38,7 +38,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-dump.h"
 #include "tree-pass.h"
 #include "diagnostic-core.h"
-#include "toplev.h"
 #include "except.h"
 #include "cfgloop.h"
 #include "cfglayout.h"
@@ -230,10 +229,6 @@ build_gimple_cfg (gimple_seq seq)
        dump_end (TDI_vcg, vcg_file);
       }
   }
-
-#ifdef ENABLE_CHECKING
-  verify_stmts ();
-#endif
 }
 
 static unsigned int
@@ -1574,7 +1569,7 @@ replace_uses_by (tree name, tree val)
          size_t i;
 
          fold_stmt_inplace (stmt);
-         if (cfgcleanup_altered_bbs)
+         if (cfgcleanup_altered_bbs && !is_gimple_debug (stmt))
            bitmap_set_bit (cfgcleanup_altered_bbs, gimple_bb (stmt)->index);
 
          /* FIXME.  This should go in update_stmt.  */
@@ -2262,7 +2257,8 @@ is_ctrl_altering_stmt (gimple 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)
+       if (!(flags & (ECF_CONST | ECF_PURE | ECF_LEAF))
+           && cfun->has_nonlocal_label)
          return true;
 
        /* A call also alters control flow if it does not return.  */
@@ -2318,7 +2314,8 @@ stmt_can_make_abnormal_goto (gimple t)
   if (computed_goto_p (t))
     return true;
   if (is_gimple_call (t))
-    return gimple_has_side_effects (t) && cfun->has_nonlocal_label;
+    return (gimple_has_side_effects (t) && cfun->has_nonlocal_label
+           && !(gimple_call_flags (t) & ECF_LEAF));
   return false;
 }
 
@@ -2613,13 +2610,13 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
       if (!POINTER_TYPE_P (TREE_TYPE (x))
          || !is_gimple_mem_ref_addr (x))
        {
-         error ("Invalid first operand of MEM_REF.");
+         error ("invalid first operand of MEM_REF");
          return x;
        }
       if (TREE_CODE (TREE_OPERAND (t, 1)) != INTEGER_CST
          || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 1))))
        {
-         error ("Invalid offset operand of MEM_REF.");
+         error ("invalid offset operand of MEM_REF");
          return TREE_OPERAND (t, 1);
        }
       if (TREE_CODE (x) == ADDR_EXPR
@@ -2638,7 +2635,7 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
       break;
 
     case MODIFY_EXPR:
-      error ("MODIFY_EXPR not expected while having tuples.");
+      error ("MODIFY_EXPR not expected while having tuples");
       return *tp;
 
     case ADDR_EXPR:
@@ -2785,7 +2782,7 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
                                     TREE_TYPE (TREE_OPERAND (t, 1))))
        {
          error ("invalid operand to pointer plus, second operand is not an "
-                "integer with type of sizetype.");
+                "integer with type of sizetype");
          return t;
        }
       /* FALLTHROUGH */
@@ -2953,14 +2950,14 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
              && (TREE_CODE (op) == SSA_NAME
                  || is_gimple_min_invariant (op)))
            {
-             error ("Conversion of an SSA_NAME on the left hand side.");
+             error ("conversion of an SSA_NAME on the left hand side");
              debug_generic_stmt (expr);
              return true;
            }
          else if (TREE_CODE (op) == SSA_NAME
                   && TYPE_SIZE (TREE_TYPE (expr)) != TYPE_SIZE (TREE_TYPE (op)))
            {
-             error ("Conversion of register to a different size.");
+             error ("conversion of register to a different size");
              debug_generic_stmt (expr);
              return true;
            }
@@ -2975,14 +2972,14 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
     {
       if (!is_gimple_mem_ref_addr (TREE_OPERAND (expr, 0)))
        {
-         error ("Invalid address operand in MEM_REF.");
+         error ("invalid address operand in MEM_REF");
          debug_generic_stmt (expr);
          return true;
        }
       if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST
          || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
        {
-         error ("Invalid offset operand in MEM_REF.");
+         error ("invalid offset operand in MEM_REF");
          debug_generic_stmt (expr);
          return true;
        }
@@ -2992,14 +2989,14 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
       if (!TMR_BASE (expr)
          || !is_gimple_mem_ref_addr (TMR_BASE (expr)))
        {
-         error ("Invalid address operand in in TARGET_MEM_REF.");
+         error ("invalid address operand in in TARGET_MEM_REF");
          return true;
        }
       if (!TMR_OFFSET (expr)
          || TREE_CODE (TMR_OFFSET (expr)) != INTEGER_CST
          || !POINTER_TYPE_P (TREE_TYPE (TMR_OFFSET (expr))))
        {
-         error ("Invalid offset operand in TARGET_MEM_REF.");
+         error ("invalid offset operand in TARGET_MEM_REF");
          debug_generic_stmt (expr);
          return true;
        }
@@ -3109,8 +3106,7 @@ verify_gimple_call (gimple stmt)
      call, and the decl should have DECL_STATIC_CHAIN set.  */
   if (gimple_call_chain (stmt))
     {
-      if (TREE_CODE (fn) != ADDR_EXPR
-         || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
+      if (!gimple_call_fndecl (stmt))
        {
          error ("static chain in indirect gimple call");
          return true;
@@ -3119,7 +3115,7 @@ verify_gimple_call (gimple stmt)
 
       if (!DECL_STATIC_CHAIN (fn))
        {
-         error ("static chain with function that doesn't use one");
+         error ("static chain with function that doesn%'t use one");
          return true;
        }
     }
@@ -3139,6 +3135,7 @@ verify_gimple_call (gimple stmt)
        {
          error ("invalid argument to gimple call");
          debug_generic_expr (arg);
+         return true;
        }
     }
 
@@ -3424,6 +3421,7 @@ verify_gimple_assign_binary (gimple stmt)
       {
        if (TREE_CODE (rhs1_type) != VECTOR_TYPE
            || !(INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
+                || POINTER_TYPE_P (TREE_TYPE (rhs1_type))
                 || FIXED_POINT_TYPE_P (TREE_TYPE (rhs1_type))
                 || SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs1_type)))
            || (!INTEGRAL_TYPE_P (rhs2_type)
@@ -3437,9 +3435,9 @@ verify_gimple_assign_binary (gimple stmt)
            debug_generic_expr (rhs2_type);
            return true;
          }
-       /* For shifting a vector of floating point components we
+       /* For shifting a vector of non-integral components we
           only allow shifting by a constant multiple of the element size.  */
-       if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs1_type))
+       if (!INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
            && (TREE_CODE (rhs2) != INTEGER_CST
                || !div_if_zero_remainder (EXACT_DIV_EXPR, rhs2,
                                           TYPE_SIZE (TREE_TYPE (rhs1_type)))))
@@ -3452,8 +3450,9 @@ verify_gimple_assign_binary (gimple stmt)
       }
 
     case PLUS_EXPR:
+    case MINUS_EXPR:
       {
-       /* We use regular PLUS_EXPR for vectors.
+       /* We use regular PLUS_EXPR and MINUS_EXPR for vectors.
           ???  This just makes the checker happy and may not be what is
           intended.  */
        if (TREE_CODE (lhs_type) == VECTOR_TYPE
@@ -3478,10 +3477,6 @@ verify_gimple_assign_binary (gimple stmt)
              }
            goto do_pointer_plus_expr_check;
          }
-      }
-    /* Fallthru.  */
-    case MINUS_EXPR:
-      {
        if (POINTER_TYPE_P (lhs_type)
            || POINTER_TYPE_P (rhs1_type)
            || POINTER_TYPE_P (rhs2_type))
@@ -3660,6 +3655,20 @@ verify_gimple_assign_ternary (gimple stmt)
        }
       break;
 
+    case FMA_EXPR:
+      if (!useless_type_conversion_p (lhs_type, rhs1_type)
+         || !useless_type_conversion_p (lhs_type, rhs2_type)
+         || !useless_type_conversion_p (lhs_type, rhs3_type))
+       {
+         error ("type mismatch in fused multiply-add expression");
+         debug_generic_expr (lhs_type);
+         debug_generic_expr (rhs1_type);
+         debug_generic_expr (rhs2_type);
+         debug_generic_expr (rhs3_type);
+         return true;
+       }
+      break;
+
     default:
       gcc_unreachable ();
     }
@@ -3702,7 +3711,13 @@ verify_gimple_assign_single (gimple stmt)
            return true;
          }
 
-       if (!types_compatible_p (TREE_TYPE (op), TREE_TYPE (TREE_TYPE (rhs1)))
+       /* Technically there is no longer a need for matching types, but
+          gimple hygiene asks for this check.  In LTO we can end up
+          combining incompatible units and thus end up with addresses
+          of globals that change their type to a common one.  */
+       if (!in_lto_p
+           && !types_compatible_p (TREE_TYPE (op),
+                                   TREE_TYPE (TREE_TYPE (rhs1)))
            && !one_pointer_to_useless_type_conversion_p (TREE_TYPE (rhs1),
                                                          TREE_TYPE (op)))
          {
@@ -3912,7 +3927,7 @@ verify_gimple_phi (gimple stmt)
 
   if (TREE_CODE (gimple_phi_result (stmt)) != SSA_NAME)
     {
-      error ("Invalid PHI result");
+      error ("invalid PHI result");
       return true;
     }
 
@@ -3924,13 +3939,13 @@ verify_gimple_phi (gimple stmt)
          || (!is_gimple_reg (gimple_phi_result (stmt))
              && !is_gimple_addressable (arg)))
        {
-         error ("Invalid PHI argument");
+         error ("invalid PHI argument");
          debug_generic_stmt (arg);
          return true;
        }
       if (!useless_type_conversion_p (type, TREE_TYPE (arg)))
        {
-         error ("Incompatible types in PHI argument %u", i);
+         error ("incompatible types in PHI argument %u", i);
          debug_generic_stmt (type);
          debug_generic_stmt (TREE_TYPE (arg));
          return true;
@@ -4235,7 +4250,7 @@ verify_eh_throw_stmt_node (void **slot, void *data)
 
   if (!pointer_set_contains (visited, node->stmt))
     {
-      error ("Dead STMT in EH table");
+      error ("dead STMT in EH table");
       debug_gimple_stmt (node->stmt);
       eh_error_found = true;
     }
@@ -5102,6 +5117,7 @@ gimple_duplicate_bb (basic_block bb)
     {
       def_operand_p def_p;
       ssa_op_iter op_iter;
+      tree lhs;
 
       stmt = gsi_stmt (gsi);
       if (gimple_code (stmt) == GIMPLE_LABEL)
@@ -5115,6 +5131,24 @@ gimple_duplicate_bb (basic_block bb)
       maybe_duplicate_eh_stmt (copy, stmt);
       gimple_duplicate_stmt_histograms (cfun, copy, cfun, stmt);
 
+      /* When copying around a stmt writing into a local non-user
+        aggregate, make sure it won't share stack slot with other
+        vars.  */
+      lhs = gimple_get_lhs (stmt);
+      if (lhs && TREE_CODE (lhs) != SSA_NAME)
+       {
+         tree base = get_base_address (lhs);
+         if (base
+             && (TREE_CODE (base) == VAR_DECL
+                 || TREE_CODE (base) == RESULT_DECL)
+             && DECL_IGNORED_P (base)
+             && !TREE_STATIC (base)
+             && !DECL_EXTERNAL (base)
+             && (TREE_CODE (base) != VAR_DECL
+                 || !DECL_HAS_VALUE_EXPR_P (base)))
+           DECL_NONSHAREABLE (base) = 1;
+       }
+
       /* Create new names for all the definitions created by COPY and
         add replacement mappings for each new name.  */
       FOR_EACH_SSA_DEF_OPERAND (def_p, copy, op_iter, SSA_OP_ALL_DEFS)
@@ -6748,7 +6782,7 @@ gimple_flow_call_edges_add (sbitmap blocks)
   if (check_last_block)
     {
       basic_block bb = EXIT_BLOCK_PTR->prev_bb;
-      gimple_stmt_iterator gsi = gsi_last_bb (bb);
+      gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
       gimple t = NULL;
 
       if (!gsi_end_p (gsi))
@@ -6782,7 +6816,7 @@ gimple_flow_call_edges_add (sbitmap blocks)
       if (blocks && !TEST_BIT (blocks, i))
        continue;
 
-      gsi = gsi_last_bb (bb);
+      gsi = gsi_last_nondebug_bb (bb);
       if (!gsi_end_p (gsi))
        {
          last_stmt = gsi_stmt (gsi);
@@ -6828,39 +6862,6 @@ gimple_flow_call_edges_add (sbitmap blocks)
   return blocks_split;
 }
 
-/* Purge dead abnormal call edges from basic block BB.  */
-
-bool
-gimple_purge_dead_abnormal_call_edges (basic_block bb)
-{
-  bool changed = gimple_purge_dead_eh_edges (bb);
-
-  if (cfun->has_nonlocal_label)
-    {
-      gimple stmt = last_stmt (bb);
-      edge_iterator ei;
-      edge e;
-
-      if (!(stmt && stmt_can_make_abnormal_goto (stmt)))
-       for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
-         {
-           if (e->flags & EDGE_ABNORMAL)
-             {
-               remove_edge (e);
-               changed = true;
-             }
-           else
-             ei_next (&ei);
-         }
-
-      /* See gimple_purge_dead_eh_edges below.  */
-      if (changed)
-       free_dominance_info (CDI_DOMINATORS);
-    }
-
-  return changed;
-}
-
 /* Removes edge E and all the blocks dominated by it, and updates dominance
    information.  The IL in E->src needs to be updated separately.
    If dominance info is not available, only the edge E is removed.*/
@@ -7014,6 +7015,8 @@ gimple_purge_dead_eh_edges (basic_block bb)
   return changed;
 }
 
+/* Purge dead EH edges from basic block listed in BLOCKS.  */
+
 bool
 gimple_purge_all_dead_eh_edges (const_bitmap blocks)
 {
@@ -7035,6 +7038,59 @@ gimple_purge_all_dead_eh_edges (const_bitmap blocks)
   return changed;
 }
 
+/* Purge dead abnormal call edges from basic block BB.  */
+
+bool
+gimple_purge_dead_abnormal_call_edges (basic_block bb)
+{
+  bool changed = false;
+  edge e;
+  edge_iterator ei;
+  gimple stmt = last_stmt (bb);
+
+  if (!cfun->has_nonlocal_label)
+    return false;
+
+  if (stmt && stmt_can_make_abnormal_goto (stmt))
+    return false;
+
+  for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
+    {
+      if (e->flags & EDGE_ABNORMAL)
+       {
+         remove_edge_and_dominated_blocks (e);
+         changed = true;
+       }
+      else
+       ei_next (&ei);
+    }
+
+  return changed;
+}
+
+/* Purge dead abnormal call edges from basic block listed in BLOCKS.  */
+
+bool
+gimple_purge_all_dead_abnormal_call_edges (const_bitmap blocks)
+{
+  bool changed = false;
+  unsigned i;
+  bitmap_iterator bi;
+
+  EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i, bi)
+    {
+      basic_block bb = BASIC_BLOCK (i);
+
+      /* Earlier gimple_purge_dead_abnormal_call_edges could have removed
+        this basic block already.  */
+      gcc_assert (bb || changed);
+      if (bb != NULL)
+       changed |= gimple_purge_dead_abnormal_call_edges (bb);
+    }
+
+  return changed;
+}
+
 /* This function is called whenever a new edge is created or
    redirected.  */
 
@@ -7141,7 +7197,7 @@ struct cfg_hooks gimple_cfg_hooks = {
   gimple_can_merge_blocks_p,   /* can_merge_blocks_p  */
   gimple_merge_blocks,         /* merge_blocks  */
   gimple_predict_edge,         /* predict_edge  */
-  gimple_predicted_by_p,               /* predicted_by_p  */
+  gimple_predicted_by_p,       /* predicted_by_p  */
   gimple_can_duplicate_bb_p,   /* can_duplicate_block_p  */
   gimple_duplicate_bb,         /* duplicate_block  */
   gimple_split_edge,           /* split_edge  */
@@ -7149,7 +7205,7 @@ struct cfg_hooks gimple_cfg_hooks = {
   NULL,                                /* tidy_fallthru_edge  */
   gimple_block_ends_with_call_p,/* block_ends_with_call_p */
   gimple_block_ends_with_condjump_p, /* block_ends_with_condjump_p */
-  gimple_flow_call_edges_add,     /* flow_call_edges_add */
+  gimple_flow_call_edges_add,   /* flow_call_edges_add */
   gimple_execute_on_growing_pred,      /* execute_on_growing_pred */
   gimple_execute_on_shrinking_pred, /* execute_on_shrinking_pred */
   gimple_duplicate_loop_to_header_edge, /* duplicate loop for trees */