OSDN Git Service

bb-reorder: Split EH edges crossing partitions.
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfg.c
index 01893ba..1207908 100644 (file)
@@ -1,6 +1,6 @@
 /* Control flow functions for trees.
    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010  Free Software Foundation, Inc.
+   2010, 2011  Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 This file is part of GCC.
@@ -261,8 +261,7 @@ struct gimple_opt_pass pass_build_cfg =
   PROP_cfg,                            /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_verify_stmts | TODO_cleanup_cfg
-  | TODO_dump_func                     /* todo_flags_finish */
+  TODO_verify_stmts | TODO_cleanup_cfg  /* todo_flags_finish */
  }
 };
 
@@ -838,12 +837,12 @@ edge_to_cases_cleanup (const void *key ATTRIBUTE_UNUSED, void **value,
 
   for (t = (tree) *value; t; t = next)
     {
-      next = TREE_CHAIN (t);
-      TREE_CHAIN (t) = NULL;
+      next = CASE_CHAIN (t);
+      CASE_CHAIN (t) = NULL;
     }
 
   *value = NULL;
-  return false;
+  return true;
 }
 
 /* Start recording information mapping edges to case labels.  */
@@ -922,7 +921,7 @@ get_cases_for_edge (edge e, gimple t)
       /* Add it to the chain of CASE_LABEL_EXPRs referencing E, or create
         a new chain.  */
       slot = pointer_map_insert (edge_to_cases, this_edge);
-      TREE_CHAIN (elt) = (tree) *slot;
+      CASE_CHAIN (elt) = (tree) *slot;
       *slot = elt;
     }
 
@@ -1358,13 +1357,14 @@ group_case_labels_stmt (gimple stmt)
        {
          tree merge_case = gimple_switch_label (stmt, i);
          tree merge_label = CASE_LABEL (merge_case);
-         tree t = int_const_binop (PLUS_EXPR, base_high,
-                                   integer_one_node, 1);
+         double_int bhp1 = double_int_add (tree_to_double_int (base_high),
+                                           double_int_one);
 
          /* Merge the cases if they jump to the same place,
             and their ranges are consecutive.  */
          if (merge_label == base_label
-             && tree_int_cst_equal (CASE_LOW (merge_case), t))
+             && double_int_equal_p (tree_to_double_int (CASE_LOW (merge_case)),
+                                    bhp1))
            {
              base_high = CASE_HIGH (merge_case) ?
                  CASE_HIGH (merge_case) : CASE_LOW (merge_case);
@@ -1421,7 +1421,7 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b)
   if (!single_succ_p (a))
     return false;
 
-  if (single_succ_edge (a)->flags & (EDGE_ABNORMAL | EDGE_EH))
+  if (single_succ_edge (a)->flags & (EDGE_ABNORMAL | EDGE_EH | EDGE_PRESERVE))
     return false;
 
   if (single_succ (a) != b)
@@ -2051,11 +2051,7 @@ gimple_dump_cfg (FILE *file, int flags)
 {
   if (flags & TDF_DETAILS)
     {
-      const char *funcname
-       = lang_hooks.decl_printable_name (current_function_decl, 2);
-
-      fputc ('\n', file);
-      fprintf (file, ";; Function %s\n\n", funcname);
+      dump_function_header (file, current_function_decl, flags);
       fprintf (file, ";; \n%d basic blocks, %d edges, last basic block %d.\n\n",
               n_basic_blocks, n_edges, last_basic_block);
 
@@ -2684,7 +2680,8 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
       break;
 
     case NON_LVALUE_EXPR:
-       gcc_unreachable ();
+    case TRUTH_NOT_EXPR:
+      gcc_unreachable ();
 
     CASE_CONVERT:
     case FIX_TRUNC_EXPR:
@@ -2692,7 +2689,6 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
     case NEGATE_EXPR:
     case ABS_EXPR:
     case BIT_NOT_EXPR:
-    case TRUTH_NOT_EXPR:
       CHECK_OP (0, "invalid operand to unary operator");
       break;
 
@@ -2829,6 +2825,14 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
        *walk_subtrees = 0;
       break;
 
+    case CASE_LABEL_EXPR:
+      if (CASE_CHAIN (t))
+       {
+         error ("invalid CASE_CHAIN");
+         return t;
+       }
+      break;
+
     default:
       break;
     }
@@ -2989,7 +2993,7 @@ 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 TARGET_MEM_REF");
          return true;
        }
       if (!TMR_OFFSET (expr)
@@ -3046,16 +3050,35 @@ verify_gimple_call (gimple stmt)
   tree fntype, fndecl;
   unsigned i;
 
-  if (!is_gimple_call_addr (fn))
+  if (gimple_call_internal_p (stmt))
+    {
+      if (fn)
+       {
+         error ("gimple call has two targets");
+         debug_generic_stmt (fn);
+         return true;
+       }
+    }
+  else
+    {
+      if (!fn)
+       {
+         error ("gimple call has no target");
+         return true;
+       }
+    }
+
+  if (fn && !is_gimple_call_addr (fn))
     {
       error ("invalid function in gimple call");
       debug_generic_stmt (fn);
       return true;
     }
 
-  if (!POINTER_TYPE_P (TREE_TYPE  (fn))
-      || (TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != FUNCTION_TYPE
-         && TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != METHOD_TYPE))
+  if (fn
+      && (!POINTER_TYPE_P (TREE_TYPE (fn))
+         || (TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != FUNCTION_TYPE
+             && TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != METHOD_TYPE)))
     {
       error ("non-function in gimple call");
       return true;
@@ -3086,8 +3109,9 @@ verify_gimple_call (gimple stmt)
       return true;
     }
 
-  fntype = TREE_TYPE (TREE_TYPE (fn));
-  if (gimple_call_lhs (stmt)
+  fntype = gimple_call_fntype (stmt);
+  if (fntype
+      && gimple_call_lhs (stmt)
       && !useless_type_conversion_p (TREE_TYPE (gimple_call_lhs (stmt)),
                                     TREE_TYPE (fntype))
       /* ???  At least C++ misses conversions at assignments from
@@ -3179,7 +3203,9 @@ verify_gimple_comparison (tree type, tree op0, tree op1)
        && (!POINTER_TYPE_P (op0_type)
           || !POINTER_TYPE_P (op1_type)
           || TYPE_MODE (op0_type) != TYPE_MODE (op1_type)))
-      || !INTEGRAL_TYPE_P (type))
+      || !INTEGRAL_TYPE_P (type)
+      || (TREE_CODE (type) != BOOLEAN_TYPE
+         && TYPE_PRECISION (type) != 1))
     {
       error ("type mismatch in comparison expression");
       debug_generic_expr (type);
@@ -3320,7 +3346,6 @@ verify_gimple_assign_unary (gimple stmt)
       /* FIXME.  */
       return false;
 
-    case TRUTH_NOT_EXPR:
     case NEGATE_EXPR:
     case ABS_EXPR:
     case BIT_NOT_EXPR:
@@ -3514,26 +3539,11 @@ do_pointer_plus_expr_check:
 
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
-      gcc_unreachable ();
-
     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
-      {
-       /* We allow any kind of integral typed argument and result.  */
-       if (!INTEGRAL_TYPE_P (rhs1_type)
-           || !INTEGRAL_TYPE_P (rhs2_type)
-           || !INTEGRAL_TYPE_P (lhs_type))
-         {
-           error ("type mismatch in binary truth expression");
-           debug_generic_expr (lhs_type);
-           debug_generic_expr (rhs1_type);
-           debug_generic_expr (rhs2_type);
-           return true;
-         }
 
-       return false;
-      }
+      gcc_unreachable ();
 
     case LT_EXPR:
     case LE_EXPR:
@@ -4851,7 +4861,7 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
              {
                last = cases;
                CASE_LABEL (cases) = label;
-               cases = TREE_CHAIN (cases);
+               cases = CASE_CHAIN (cases);
              }
 
            /* If there was already an edge in the CFG, then we need
@@ -4860,8 +4870,8 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
              {
                tree cases2 = get_cases_for_edge (e2, stmt);
 
-               TREE_CHAIN (last) = TREE_CHAIN (cases2);
-               TREE_CHAIN (cases2) = first;
+               CASE_CHAIN (last) = CASE_CHAIN (cases2);
+               CASE_CHAIN (cases2) = first;
              }
            bitmap_set_bit (touched_switch_bbs, gimple_bb (stmt)->index);
          }
@@ -5068,6 +5078,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)
@@ -5081,6 +5092,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)
@@ -5371,12 +5400,10 @@ gimple_duplicate_sese_tail (edge entry ATTRIBUTE_UNUSED, edge exit ATTRIBUTE_UNU
   int total_freq = 0, exit_freq = 0;
   gcov_type total_count = 0, exit_count = 0;
   edge exits[2], nexits[2], e;
-  gimple_stmt_iterator gsi,gsi1;
+  gimple_stmt_iterator gsi;
   gimple cond_stmt;
   edge sorig, snew;
   basic_block exit_bb;
-  basic_block iters_bb;
-  tree new_rhs;
   gimple_stmt_iterator psi;
   gimple phi;
   tree def;
@@ -5457,35 +5484,6 @@ gimple_duplicate_sese_tail (edge entry ATTRIBUTE_UNUSED, edge exit ATTRIBUTE_UNU
   gcc_assert (gimple_code (cond_stmt) == GIMPLE_COND);
   cond_stmt = gimple_copy (cond_stmt);
 
- /* If the block consisting of the exit condition has the latch as
-    successor, then the body of the loop is executed before
-    the exit condition is tested.  In such case, moving the
-    condition to the entry, causes that the loop will iterate
-    one less iteration (which is the wanted outcome, since we
-    peel out the last iteration).  If the body is executed after
-    the condition, moving the condition to the entry requires
-    decrementing one iteration.  */
-  if (exits[1]->dest == orig_loop->latch)
-    new_rhs = gimple_cond_rhs (cond_stmt);
-  else
-  {
-    new_rhs = fold_build2 (MINUS_EXPR, TREE_TYPE (gimple_cond_rhs (cond_stmt)),
-                          gimple_cond_rhs (cond_stmt),
-                          build_int_cst (TREE_TYPE (gimple_cond_rhs (cond_stmt)), 1));
-
-    if (TREE_CODE (gimple_cond_rhs (cond_stmt)) == SSA_NAME)
-      {
-       iters_bb = gimple_bb (SSA_NAME_DEF_STMT (gimple_cond_rhs (cond_stmt)));
-       for (gsi1 = gsi_start_bb (iters_bb); !gsi_end_p (gsi1); gsi_next (&gsi1))
-         if (gsi_stmt (gsi1) == SSA_NAME_DEF_STMT (gimple_cond_rhs (cond_stmt)))
-           break;
-
-       new_rhs = force_gimple_operand_gsi (&gsi1, new_rhs, true,
-                                           NULL_TREE,false,GSI_CONTINUE_LINKING);
-      }
-  }
-  gimple_cond_set_rhs (cond_stmt, unshare_expr (new_rhs));
-  gimple_cond_set_lhs (cond_stmt, unshare_expr (gimple_cond_lhs (cond_stmt)));
   gsi_insert_after (&gsi, cond_stmt, GSI_NEW_STMT);
 
   sorig = single_succ_edge (switch_bb);
@@ -5736,7 +5734,7 @@ move_stmt_eh_region_tree_nr (tree old_t_nr, struct move_stmt_d *p)
   old_nr = tree_low_cst (old_t_nr, 0);
   new_nr = move_stmt_eh_region_nr (old_nr, p);
 
-  return build_int_cst (NULL, new_nr);
+  return build_int_cst (integer_type_node, new_nr);
 }
 
 /* Like move_stmt_op, but for gimple statements.
@@ -7135,6 +7133,7 @@ struct cfg_hooks gimple_cfg_hooks = {
   gimple_split_edge,           /* split_edge  */
   gimple_make_forwarder_block, /* make_forward_block  */
   NULL,                                /* tidy_fallthru_edge  */
+  NULL,                                /* force_nonfallthru */
   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 */
@@ -7211,7 +7210,7 @@ struct gimple_opt_pass pass_split_crit_edges =
   PROP_no_crit_edges,            /* properties_provided */
   0,                             /* properties_destroyed */
   0,                             /* todo_flags_start */
-  TODO_dump_func | TODO_verify_flow  /* todo_flags_finish */
+  TODO_verify_flow               /* todo_flags_finish */
  }
 };
 
@@ -7435,12 +7434,14 @@ do_warn_unused_result (gimple_seq seq)
        case GIMPLE_CALL:
          if (gimple_call_lhs (g))
            break;
+         if (gimple_call_internal_p (g))
+           break;
 
          /* This is a naked call, as opposed to a GIMPLE_CALL with an
             LHS.  All calls whose value is ignored should be
             represented like this.  Look for the attribute.  */
          fdecl = gimple_call_fndecl (g);
-         ftype = TREE_TYPE (TREE_TYPE (gimple_call_fn (g)));
+         ftype = gimple_call_fntype (g);
 
          if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
            {
@@ -7496,4 +7497,3 @@ struct gimple_opt_pass pass_warn_unused_result =
     0,                                 /* todo_flags_finish */
   }
 };
-