OSDN Git Service

2010-12-09 Martin Jambor <mjambor@suse.cz>
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfg.c
index cf67fb8..e3ab9d9 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"
@@ -1570,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.  */
@@ -2611,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
@@ -2636,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:
@@ -2783,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 */
@@ -2951,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;
            }
@@ -2973,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;
        }
@@ -2990,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;
        }
@@ -3107,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;
@@ -3117,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;
        }
     }
@@ -3422,6 +3420,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)
@@ -3435,9 +3434,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)))))
@@ -3655,6 +3654,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 ();
     }
@@ -3697,7 +3710,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)))
          {
@@ -3907,7 +3926,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;
     }
 
@@ -3919,13 +3938,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;
@@ -4230,7 +4249,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;
     }
@@ -6743,7 +6762,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))
@@ -6777,7 +6796,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);
@@ -6823,39 +6842,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.*/
@@ -7009,6 +6995,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)
 {
@@ -7030,6 +7018,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.  */