OSDN Git Service

* tree-vect-patterns.c (vect_single_imm_use): Correct return
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfg.c
index b733c88..c4a1ffa 100644 (file)
@@ -1,6 +1,6 @@
 /* Control flow functions for trees.
    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
 /* Control flow functions for trees.
    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010, 2011  Free Software Foundation, Inc.
+   2010, 2011, 2012  Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 This file is part of GCC.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 This file is part of GCC.
@@ -1592,7 +1592,7 @@ replace_uses_by (tree name, tree val)
                  /* This can only occur for virtual operands, since
                     for the real ones SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
                     would prevent replacement.  */
                  /* This can only occur for virtual operands, since
                     for the real ones SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
                     would prevent replacement.  */
-                 gcc_assert (!is_gimple_reg (name));
+                 gcc_checking_assert (!is_gimple_reg (name));
                  SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val) = 1;
                }
            }
                  SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val) = 1;
                }
            }
@@ -1601,30 +1601,40 @@ replace_uses_by (tree name, tree val)
       if (gimple_code (stmt) != GIMPLE_PHI)
        {
          gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
       if (gimple_code (stmt) != GIMPLE_PHI)
        {
          gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+         gimple orig_stmt = stmt;
          size_t i;
 
          size_t i;
 
-         fold_stmt (&gsi);
-         stmt = gsi_stmt (gsi);
-         if (cfgcleanup_altered_bbs && !is_gimple_debug (stmt))
+         /* Mark the block if we changed the last stmt in it.  */
+         if (cfgcleanup_altered_bbs
+             && stmt_ends_bb_p (stmt))
            bitmap_set_bit (cfgcleanup_altered_bbs, gimple_bb (stmt)->index);
 
            bitmap_set_bit (cfgcleanup_altered_bbs, gimple_bb (stmt)->index);
 
-         /* FIXME.  This should go in update_stmt.  */
-         for (i = 0; i < gimple_num_ops (stmt); i++)
-           {
-             tree op = gimple_op (stmt, i);
-              /* Operands may be empty here.  For example, the labels
-                 of a GIMPLE_COND are nulled out following the creation
-                 of the corresponding CFG edges.  */
-             if (op && TREE_CODE (op) == ADDR_EXPR)
-               recompute_tree_invariant_for_addr_expr (op);
-           }
+         /* FIXME.  It shouldn't be required to keep TREE_CONSTANT
+            on ADDR_EXPRs up-to-date on GIMPLE.  Propagation will
+            only change sth from non-invariant to invariant, and only
+            when propagating constants.  */
+         if (is_gimple_min_invariant (val))
+           for (i = 0; i < gimple_num_ops (stmt); i++)
+             {
+               tree op = gimple_op (stmt, i);
+               /* Operands may be empty here.  For example, the labels
+                  of a GIMPLE_COND are nulled out following the creation
+                  of the corresponding CFG edges.  */
+               if (op && TREE_CODE (op) == ADDR_EXPR)
+                 recompute_tree_invariant_for_addr_expr (op);
+             }
+
+         if (fold_stmt (&gsi))
+           stmt = gsi_stmt (gsi);
+
+         if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt))
+           gimple_purge_dead_eh_edges (gimple_bb (stmt));
 
 
-         maybe_clean_or_replace_eh_stmt (stmt, stmt);
          update_stmt (stmt);
        }
     }
 
          update_stmt (stmt);
        }
     }
 
-  gcc_assert (has_zero_uses (name));
+  gcc_checking_assert (has_zero_uses (name));
 
   /* Also update the trees stored in loop structures.  */
   if (current_loops)
 
   /* Also update the trees stored in loop structures.  */
   if (current_loops)
@@ -2263,6 +2273,43 @@ gimple_cfg2vcg (FILE *file)
                             Miscellaneous helpers
 ---------------------------------------------------------------------------*/
 
                             Miscellaneous helpers
 ---------------------------------------------------------------------------*/
 
+/* Return true if T, a GIMPLE_CALL, can make an abnormal transfer of control
+   flow.  Transfers of control flow associated with EH are excluded.  */
+
+static bool
+call_can_make_abnormal_goto (gimple t)
+{
+  /* If the function has no non-local labels, then a call cannot make an
+     abnormal transfer of control.  */
+  if (!cfun->has_nonlocal_label)
+   return false;
+
+  /* Likewise if the call has no side effects.  */
+  if (!gimple_has_side_effects (t))
+    return false;
+
+  /* Likewise if the called function is leaf.  */
+  if (gimple_call_flags (t) & ECF_LEAF)
+    return false;
+
+  return true;
+}
+
+
+/* Return true if T can make an abnormal transfer of control flow.
+   Transfers of control flow associated with EH are excluded.  */
+
+bool
+stmt_can_make_abnormal_goto (gimple t)
+{
+  if (computed_goto_p (t))
+    return true;
+  if (is_gimple_call (t))
+    return call_can_make_abnormal_goto (t);
+  return false;
+}
+
+
 /* Return true if T represents a stmt that always transfers control.  */
 
 bool
 /* Return true if T represents a stmt that always transfers control.  */
 
 bool
@@ -2296,10 +2343,8 @@ is_ctrl_altering_stmt (gimple t)
       {
        int flags = gimple_call_flags (t);
 
       {
        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 | ECF_LEAF))
-           && cfun->has_nonlocal_label)
+       /* A call alters control flow if it can make an abnormal goto.  */
+       if (call_can_make_abnormal_goto (t))
          return true;
 
        /* A call also alters control flow if it does not return.  */
          return true;
 
        /* A call also alters control flow if it does not return.  */
@@ -2357,21 +2402,6 @@ simple_goto_p (gimple t)
 }
 
 
 }
 
 
-/* Return true if T can make an abnormal transfer of control flow.
-   Transfers of control flow associated with EH are excluded.  */
-
-bool
-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
-           && !(gimple_call_flags (t) & ECF_LEAF));
-  return false;
-}
-
-
 /* Return true if STMT should start a new basic block.  PREV_STMT is
    the statement preceding STMT.  It is used when STMT is a label or a
    case label.  Labels should only start a new basic block if their
 /* Return true if STMT should start a new basic block.  PREV_STMT is
    the statement preceding STMT.  It is used when STMT is a label or a
    case label.  Labels should only start a new basic block if their
@@ -3227,16 +3257,6 @@ verify_gimple_call (gimple stmt)
        }
     }
 
        }
     }
 
-  /* Verify that if we have a direct call and the argument/return
-     types have mismatches the call is properly marked as noninlinable.  */
-  if (fndecl
-      && !gimple_call_cannot_inline_p (stmt)
-      && !gimple_check_call_matching_types (stmt, fndecl))
-    {
-      error ("gimple call cannot be inlined but is not marked so");
-      return true;
-    }
-
   return false;
 }
 
   return false;
 }
 
@@ -3340,15 +3360,12 @@ verify_gimple_assign_unary (gimple stmt)
     {
     CASE_CONVERT:
       {
     {
     CASE_CONVERT:
       {
-       /* Allow conversions between integral types and pointers only if
+       /* Allow conversions from pointer type to integral type only if
           there is no sign or zero extension involved.
           For targets were the precision of ptrofftype doesn't match that
           there is no sign or zero extension involved.
           For targets were the precision of ptrofftype doesn't match that
-          of pointers we need to allow arbitrary conversions from and
-          to ptrofftype.  */
+          of pointers we need to allow arbitrary conversions to ptrofftype.  */
        if ((POINTER_TYPE_P (lhs_type)
        if ((POINTER_TYPE_P (lhs_type)
-            && INTEGRAL_TYPE_P (rhs1_type)
-            && (TYPE_PRECISION (lhs_type) >= TYPE_PRECISION (rhs1_type)
-                || ptrofftype_p (rhs1_type)))
+            && INTEGRAL_TYPE_P (rhs1_type))
            || (POINTER_TYPE_P (rhs1_type)
                && INTEGRAL_TYPE_P (lhs_type)
                && (TYPE_PRECISION (rhs1_type) >= TYPE_PRECISION (lhs_type)
            || (POINTER_TYPE_P (rhs1_type)
                && INTEGRAL_TYPE_P (lhs_type)
                && (TYPE_PRECISION (rhs1_type) >= TYPE_PRECISION (lhs_type)
@@ -3711,10 +3728,6 @@ do_pointer_plus_expr_check:
     case VEC_PACK_TRUNC_EXPR:
     case VEC_PACK_SAT_EXPR:
     case VEC_PACK_FIX_TRUNC_EXPR:
     case VEC_PACK_TRUNC_EXPR:
     case VEC_PACK_SAT_EXPR:
     case VEC_PACK_FIX_TRUNC_EXPR:
-    case VEC_EXTRACT_EVEN_EXPR:
-    case VEC_EXTRACT_ODD_EXPR:
-    case VEC_INTERLEAVE_HIGH_EXPR:
-    case VEC_INTERLEAVE_LOW_EXPR:
       /* FIXME.  */
       return false;
 
       /* FIXME.  */
       return false;
 
@@ -6886,9 +6899,20 @@ need_fake_edge_p (gimple t)
           && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FORK))
     return false;
 
           && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FORK))
     return false;
 
-  if (is_gimple_call (t)
-      && !(call_flags & ECF_NORETURN))
-    return true;
+  if (is_gimple_call (t))
+    {
+      edge_iterator ei;
+      edge e;
+      basic_block bb;
+
+      if (!(call_flags & ECF_NORETURN))
+       return true;
+
+      bb = gimple_bb (t);
+      FOR_EACH_EDGE (e, ei, bb->succs)
+       if ((e->flags & EDGE_FAKE) == 0)
+         return true;
+    }
 
   if (gimple_code (t) == GIMPLE_ASM
        && (gimple_asm_volatile_p (t) || gimple_asm_input_p (t)))
 
   if (gimple_code (t) == GIMPLE_ASM
        && (gimple_asm_volatile_p (t) || gimple_asm_input_p (t)))
@@ -6899,9 +6923,10 @@ need_fake_edge_p (gimple t)
 
 
 /* Add fake edges to the function exit for any non constant and non
 
 
 /* Add fake edges to the function exit for any non constant and non
-   noreturn calls, volatile inline assembly in the bitmap of blocks
-   specified by BLOCKS or to the whole CFG if BLOCKS is zero.  Return
-   the number of blocks that were split.
+   noreturn calls (or noreturn calls with EH/abnormal edges),
+   volatile inline assembly in the bitmap of blocks specified by BLOCKS
+   or to the whole CFG if BLOCKS is zero.  Return the number of blocks
+   that were split.
 
    The goal is to expose cases in which entering a basic block does
    not imply that all subsequent instructions must be executed.  */
 
    The goal is to expose cases in which entering a basic block does
    not imply that all subsequent instructions must be executed.  */