OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfg.c
index 944b31f..5dc9d04 100644 (file)
@@ -1060,18 +1060,23 @@ group_case_labels (void)
          tree labels = SWITCH_LABELS (stmt);
          int old_size = TREE_VEC_LENGTH (labels);
          int i, j, new_size = old_size;
-         tree default_case = TREE_VEC_ELT (labels, old_size - 1);
-         tree default_label;
+         tree default_case = NULL_TREE;
+         tree default_label = NULL_TREE;
 
          /* The default label is always the last case in a switch
-            statement after gimplification.  */
-         default_label = CASE_LABEL (default_case);
+            statement after gimplification if it was not optimized
+            away.  */
+         if (!CASE_LOW (TREE_VEC_ELT (labels, old_size - 1))
+             && !CASE_HIGH (TREE_VEC_ELT (labels, old_size - 1)))
+           {
+             default_case = TREE_VEC_ELT (labels, old_size - 1);
+             default_label = CASE_LABEL (default_case);
+             old_size--;
+           }
 
-         /* Look for possible opportunities to merge cases.
-            Ignore the last element of the label vector because it
-            must be the default case.  */
+         /* Look for possible opportunities to merge cases.  */
           i = 0;
-         while (i < old_size - 1)
+         while (i < old_size)
            {
              tree base_case, base_label, base_high;
              base_case = TREE_VEC_ELT (labels, i);
@@ -1095,7 +1100,7 @@ group_case_labels (void)
              /* Try to merge case labels.  Break out when we reach the end
                 of the label vector or when we cannot merge the next case
                 label with the current one.  */
-             while (i < old_size - 1)
+             while (i < old_size)
                {
                  tree merge_case = TREE_VEC_ELT (labels, i);
                  tree merge_label = CASE_LABEL (merge_case);
@@ -1803,9 +1808,9 @@ notice_special_calls (tree t)
   int flags = call_expr_flags (t);
 
   if (flags & ECF_MAY_BE_ALLOCA)
-    current_function_calls_alloca = true;
+    cfun->calls_alloca = true;
   if (flags & ECF_RETURNS_TWICE)
-    current_function_calls_setjmp = true;
+    cfun->calls_setjmp = true;
 }
 
 
@@ -1815,8 +1820,8 @@ notice_special_calls (tree t)
 void
 clear_special_calls (void)
 {
-  current_function_calls_alloca = false;
-  current_function_calls_setjmp = false;
+  cfun->calls_alloca = false;
+  cfun->calls_setjmp = false;
 }
 
 
@@ -1912,6 +1917,33 @@ remove_useless_stmts_1 (tree *tp, struct rus_data *data)
       data->last_goto = NULL;
       break;
 
+    case OMP_PARALLEL:
+      /* Make sure the outermost BIND_EXPR in OMP_BODY isn't removed
+        as useless.  */
+      remove_useless_stmts_1 (&BIND_EXPR_BODY (OMP_BODY (*tp)), data);
+      data->last_goto = NULL;
+      break;
+
+    case OMP_SECTIONS:
+    case OMP_SINGLE:
+    case OMP_SECTION:
+    case OMP_MASTER :
+    case OMP_ORDERED:
+    case OMP_CRITICAL:
+      remove_useless_stmts_1 (&OMP_BODY (*tp), data);
+      data->last_goto = NULL;
+      break;
+
+    case OMP_FOR:
+      remove_useless_stmts_1 (&OMP_FOR_BODY (*tp), data);
+      data->last_goto = NULL;
+      if (OMP_FOR_PRE_BODY (*tp))
+       {
+         remove_useless_stmts_1 (&OMP_FOR_PRE_BODY (*tp), data);
+         data->last_goto = NULL;
+       }
+      break;
+
     default:
       data->last_goto = NULL;
       break;
@@ -2463,7 +2495,7 @@ is_ctrl_altering_stmt (const_tree t)
     {
       /* A non-pure/const CALL_EXPR alters flow control if the current
         function has nonlocal labels.  */
-      if (TREE_SIDE_EFFECTS (call) && current_function_has_nonlocal_label)
+      if (TREE_SIDE_EFFECTS (call) && cfun->has_nonlocal_label)
        return true;
 
       /* A CALL_EXPR also alters control flow if it does not return.  */
@@ -2513,7 +2545,7 @@ tree_can_make_abnormal_goto (const_tree t)
   if (TREE_CODE (t) == WITH_SIZE_EXPR)
     t = TREE_OPERAND (t, 0);
   if (TREE_CODE (t) == CALL_EXPR)
-    return TREE_SIDE_EFFECTS (t) && current_function_has_nonlocal_label;
+    return TREE_SIDE_EFFECTS (t) && cfun->has_nonlocal_label;
   return false;
 }
 
@@ -2665,7 +2697,7 @@ set_bb_for_stmt (tree t, basic_block bb)
          if (uid == -1)
            {
              unsigned old_len = VEC_length (basic_block, label_to_block_map);
-             LABEL_DECL_UID (t) = uid = cfun->last_label_uid++;
+             LABEL_DECL_UID (t) = uid = cfun->cfg->last_label_uid++;
              if (old_len <= (unsigned) uid)
                {
                  unsigned new_len = 3 * uid / 2;
@@ -3156,28 +3188,20 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 
     case ADDR_EXPR:
       {
-       bool old_invariant;
        bool old_constant;
        bool old_side_effects;
-       bool new_invariant;
        bool new_constant;
        bool new_side_effects;
 
-       old_invariant = TREE_INVARIANT (t);
+       gcc_assert (is_gimple_address (t));
+
        old_constant = TREE_CONSTANT (t);
        old_side_effects = TREE_SIDE_EFFECTS (t);
 
        recompute_tree_invariant_for_addr_expr (t);
-       new_invariant = TREE_INVARIANT (t);
        new_side_effects = TREE_SIDE_EFFECTS (t);
        new_constant = TREE_CONSTANT (t);
 
-       if (old_invariant != new_invariant)
-         {
-           error ("invariant not recomputed when ADDR_EXPR changed");
-           return t;
-         }
-
         if (old_constant != new_constant)
          {
            error ("constant not recomputed when ADDR_EXPR changed");
@@ -3222,6 +3246,9 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
        }
       break;
 
+    case NON_LVALUE_EXPR:
+       gcc_unreachable ();
+
     case NOP_EXPR:
     case CONVERT_EXPR:
     case FIX_TRUNC_EXPR:
@@ -3229,7 +3256,6 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
     case NEGATE_EXPR:
     case ABS_EXPR:
     case BIT_NOT_EXPR:
-    case NON_LVALUE_EXPR:
     case TRUTH_NOT_EXPR:
       CHECK_OP (0, "invalid operand to unary operator");
       break;
@@ -3822,6 +3848,8 @@ verify_gimple_expr (tree expr)
 
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
+      gcc_unreachable ();
+
     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
@@ -4149,6 +4177,11 @@ verify_stmt (tree stmt, bool last_in_block)
   if (addr)
     {
       debug_generic_stmt (addr);
+      if (addr != stmt)
+       {
+         inform ("in statement");
+         debug_generic_stmt (stmt);
+       }
       return true;
     }
 
@@ -4604,13 +4637,16 @@ tree_verify_flow_info (void)
 
            /* Verify that the case labels are sorted.  */
            prev = TREE_VEC_ELT (vec, 0);
-           for (i = 1; i < n - 1; ++i)
+           for (i = 1; i < n; ++i)
              {
                tree c = TREE_VEC_ELT (vec, i);
                if (! CASE_LOW (c))
                  {
-                   error ("found default case not at end of case vector");
-                   err = 1;
+                   if (i != n - 1)
+                     {
+                       error ("found default case not at end of case vector");
+                       err = 1;
+                     }
                    continue;
                  }
                if (! tree_int_cst_lt (CASE_LOW (prev), CASE_LOW (c)))
@@ -4624,11 +4660,9 @@ tree_verify_flow_info (void)
                  }
                prev = c;
              }
-           if (CASE_LOW (TREE_VEC_ELT (vec, n - 1)))
-             {
-               error ("no default case found at end of case vector");
-               err = 1;
-             }
+           /* VRP will remove the default case if it can prove it will
+              never be executed.  So do not verify there always exists
+              a default case here.  */
 
            FOR_EACH_EDGE (e, ei, bb->succs)
              {
@@ -5471,7 +5505,7 @@ DEF_VEC_ALLOC_P(basic_block,heap);
    adding blocks when the dominator traversal reaches EXIT.  This
    function silently assumes that ENTRY strictly dominates EXIT.  */
 
-static void
+void
 gather_blocks_in_sese_region (basic_block entry, basic_block exit,
                              VEC(basic_block,heap) **bbs_p)
 {
@@ -5510,8 +5544,7 @@ replace_by_duplicate_decl (tree *tp, struct pointer_map_t *vars_map,
       if (SSA_VAR_P (t))
        {
          new_t = copy_var_decl (t, DECL_NAME (t), TREE_TYPE (t));
-         f->unexpanded_var_list
-                 = tree_cons (NULL_TREE, new_t, f->unexpanded_var_list);
+         f->local_decls = tree_cons (NULL_TREE, new_t, f->local_decls);
        }
       else
        {
@@ -5804,8 +5837,8 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
 
          gcc_assert (DECL_CONTEXT (label) == dest_cfun->decl);
 
-         if (uid >= dest_cfun->last_label_uid)
-           dest_cfun->last_label_uid = uid + 1;
+         if (uid >= dest_cfun->cfg->last_label_uid)
+           dest_cfun->cfg->last_label_uid = uid + 1;
        }
       else if (TREE_CODE (stmt) == RESX_EXPR && eh_offset != 0)
        TREE_OPERAND (stmt, 0) =
@@ -5878,8 +5911,8 @@ new_label_mapper (tree decl, void *data)
   m->base.from = decl;
   m->to = create_artificial_label ();
   LABEL_DECL_UID (m->to) = LABEL_DECL_UID (decl);
-  if (LABEL_DECL_UID (m->to) >= cfun->last_label_uid)
-    cfun->last_label_uid = LABEL_DECL_UID (m->to) + 1;
+  if (LABEL_DECL_UID (m->to) >= cfun->cfg->last_label_uid)
+    cfun->cfg->last_label_uid = LABEL_DECL_UID (m->to) + 1;
 
   slot = htab_find_slot_with_hash (hash, m, m->hash, INSERT);
   gcc_assert (*slot == NULL);
@@ -6097,6 +6130,8 @@ dump_function_to_file (tree fn, FILE *file, int flags)
   arg = DECL_ARGUMENTS (fn);
   while (arg)
     {
+      print_generic_expr (file, TREE_TYPE (arg), dump_flags);
+      fprintf (file, " ");
       print_generic_expr (file, arg, dump_flags);
       if (TREE_CHAIN (arg))
        fprintf (file, ", ");
@@ -6119,12 +6154,12 @@ dump_function_to_file (tree fn, FILE *file, int flags)
 
   /* When GIMPLE is lowered, the variables are no longer available in
      BIND_EXPRs, so display them separately.  */
-  if (cfun && cfun->decl == fn && cfun->unexpanded_var_list)
+  if (cfun && cfun->decl == fn && cfun->local_decls)
     {
       ignore_topmost_bind = true;
 
       fprintf (file, "{\n");
-      for (vars = cfun->unexpanded_var_list; vars; vars = TREE_CHAIN (vars))
+      for (vars = cfun->local_decls; vars; vars = TREE_CHAIN (vars))
        {
          var = TREE_VALUE (vars);
 
@@ -6387,7 +6422,8 @@ tree_block_ends_with_condjump_p (const_basic_block bb)
 static bool
 need_fake_edge_p (tree t)
 {
-  tree call;
+  tree call, fndecl = NULL_TREE;
+  int call_flags;
 
   /* NORETURN and LONGJMP calls already have an edge to exit.
      CONST and PURE calls do not need one.
@@ -6397,8 +6433,19 @@ need_fake_edge_p (tree t)
      the counter incrementation code from -fprofile-arcs
      leads to different results from -fbranch-probabilities.  */
   call = get_call_expr_in (t);
-  if (call
-      && !(call_expr_flags (call) & ECF_NORETURN))
+  if (call)
+    {
+      fndecl = get_callee_fndecl (call);
+      call_flags = call_expr_flags (call);
+    }
+
+  if (call && fndecl && DECL_BUILT_IN (fndecl)
+      && (call_flags & ECF_NOTHROW)
+      && !(call_flags & ECF_NORETURN)
+      && !(call_flags & ECF_RETURNS_TWICE))
+   return false;
+
+  if (call && !(call_flags & ECF_NORETURN))
     return true;
 
   if (TREE_CODE (t) == ASM_EXPR
@@ -6533,7 +6580,7 @@ tree_purge_dead_abnormal_call_edges (basic_block bb)
 {
   bool changed = tree_purge_dead_eh_edges (bb);
 
-  if (current_function_has_nonlocal_label)
+  if (cfun->has_nonlocal_label)
     {
       tree stmt = last_stmt (bb);
       edge_iterator ei;
@@ -7079,7 +7126,7 @@ execute_warn_function_noreturn (void)
   if (warn_missing_noreturn
       && !TREE_THIS_VOLATILE (cfun->decl)
       && EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 0
-      && !lang_hooks.function.missing_noreturn_ok_p (cfun->decl))
+      && !lang_hooks.missing_noreturn_ok_p (cfun->decl))
     warning (OPT_Wmissing_noreturn, "%Jfunction might be possible candidate "
             "for attribute %<noreturn%>",
             cfun->decl);