+2012-08-24  Martin Jambor  <mjambor@suse.cz>
+
+       * predict.c (maybe_hot_frequency_p): New parameter fun.  Use its decl
+       instead of current_function_decl, use profile_status_for_function and
+       ENTRY_BLOCK_PTR_FOR_FUNCTION with fun instead of their cfun variants.
+       (maybe_hot_count_p): New parameter fun, use
+       profile_status_for_function instead of its cfun_variant.
+       (maybe_hot_bb_p): New parameter fun, checking-assert it, pass it to
+       all callees.
+       (maybe_hot_edge_p): Pass cfun to maybe_hot_count_p and
+       maybe_hot_frequency_p.
+       (probably_never_executed_bb_p): New parameter fun, use its decl
+       instead of current_function_decl.
+       (optimize_bb_for_size_p): Pass cfun to maybe_hot_bb_p.
+       (rtl_profile_for_bb): Likewise.
+       (compute_function_frequency): Pass cfun to maybe_hot_bb_p and
+       probably_never_executed_bb_p.
+       * tree-ssa-operands.c (ssa_operands_active): New operator fun.  Use it
+       instead of cfun.
+       (update_stmt_operands): Pass cfun as an argument of
+       ssa_operands_active.
+       (swap_tree_operands): Likewise.
+       * gimple-iterator.c (update_modified_stmt): Likewise.
+       (update_modified_stmts): Likewise.
+       * tree-flow-inline.h (delink_stmt_imm_use): Likewise.
+       * tree-ssa.c (delete_tree_ssa): Likewise.
+       * bb-reorder.c (bb_to_key): Pass cfun to probably_never_executed_bb_p.
+       (push_to_next_round_p): Likewise.
+       (find_rarely_executed_basic_blocks_and_crossing_edges ): Likewise.
+       * cfg.c: Inlude tree.h.
+       (check_bb_profile): Use profile_status_for_function,
+       EXIT_BLOCK_PTR_FOR_FUNCTION and ENTRY_BLOCK_PTR_FOR_FUNCTION with
+       DECL_STRUCT_FUNCTION (current_function_decl) instead of their cfun
+       variants.
+       (dump_bb_info): Pass DECL_STRUCT_FUNCTION (current_function_decl) to
+       maybe_hot_bb_p and probably_never_executed_bb_p.
+       * gimple-pretty-print.c (gimple_dump_bb_buff): Checking-assert that
+       DECL_STRUCT_FUNCTION (current_function_decl) is not NULL.  Pass it to
+       dump_histograms_for_stmt.
+       (dump_gimple_mem_ops): Pass DECL_STRUCT_FUNCTION (current_function_decl)
+       as an argument to dump_gimple_mem_ops.
+       * tree-cfg.c (dump_function_to_file): Rename parameter fn to fndecl.
+       Do not change cfun.  Change and restore current_function_decl.
+       * Makefile.in (cfg.o): Include TREE_H in dependencies.
+
 2012-08-24  Georg-Johann Lay  <avr@gjlay.de>
 
        PR target/54222
 
    $(REGS_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) \
    $(EXPR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H)
 cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h $(DIAGNOSTIC_CORE_H) \
-   $(GGC_H) $(OBSTACK_H) alloc-pool.h $(HASHTAB_H) $(CFGLOOP_H) $(BASIC_BLOCK_H)
+   $(GGC_H) $(OBSTACK_H) alloc-pool.h $(HASHTAB_H) $(CFGLOOP_H) $(TREE_H) \
+   $(BASIC_BLOCK_H)
 cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TIMEVAR_H) toplev.h $(DIAGNOSTIC_CORE_H) $(CFGLOOP_H)
 cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
 
 extern void compute_available (sbitmap *, sbitmap *, sbitmap *, sbitmap *);
 
 /* In predict.c */
-extern bool maybe_hot_bb_p (const_basic_block);
+extern bool maybe_hot_bb_p (struct function *, const_basic_block);
 extern bool maybe_hot_edge_p (edge);
-extern bool probably_never_executed_bb_p (const_basic_block);
+extern bool probably_never_executed_bb_p (struct function *, const_basic_block);
 extern bool optimize_bb_for_size_p (const_basic_block);
 extern bool optimize_bb_for_speed_p (const_basic_block);
 extern bool optimize_edge_for_size_p (edge);
 
 
   block_not_hot_enough = (bb->frequency < exec_th
                          || bb->count < count_th
-                         || probably_never_executed_bb_p (bb));
+                         || probably_never_executed_bb_p (cfun, bb));
 
   if (there_exists_another_round
       && block_not_hot_enough)
   /* Do not start in probably never executed blocks.  */
 
   if (BB_PARTITION (bb) == BB_COLD_PARTITION
-      || probably_never_executed_bb_p (bb))
+      || probably_never_executed_bb_p (cfun, bb))
     return BB_FREQ_MAX;
 
   /* Prefer blocks whose predecessor is an end of some trace
   /* Mark which partition (hot/cold) each basic block belongs in.  */
   FOR_EACH_BB (bb)
     {
-      if (probably_never_executed_bb_p (bb))
+      if (probably_never_executed_bb_p (cfun, bb))
        BB_SET_PARTITION (bb, BB_COLD_PARTITION);
       else
        BB_SET_PARTITION (bb, BB_HOT_PARTITION);
 
 #include "ggc.h"
 #include "hashtab.h"
 #include "alloc-pool.h"
+#include "tree.h"
 #include "basic-block.h"
 #include "df.h"
 #include "cfgloop.h" /* FIXME: For struct loop.  */
   int sum = 0;
   gcov_type lsum;
   edge_iterator ei;
+  struct function *fun = DECL_STRUCT_FUNCTION (current_function_decl);
   char *s_indent = (char *) alloca ((size_t) indent + 1);
   memset ((void *) s_indent, ' ', (size_t) indent);
   s_indent[indent] = '\0';
 
-  if (profile_status == PROFILE_ABSENT)
+  if (profile_status_for_function (fun) == PROFILE_ABSENT)
     return;
 
-  if (bb != EXIT_BLOCK_PTR)
+  if (bb != EXIT_BLOCK_PTR_FOR_FUNCTION (fun))
     {
       FOR_EACH_EDGE (e, ei, bb->succs)
        sum += e->probability;
                 (flags & TDF_COMMENT) ? ";; " : "", s_indent,
                 (int) lsum, (int) bb->count);
     }
-  if (bb != ENTRY_BLOCK_PTR)
+    if (bb != ENTRY_BLOCK_PTR_FOR_FUNCTION (fun))
     {
       sum = 0;
       FOR_EACH_EDGE (e, ei, bb->preds)
               s_indent, bb->index, bb_loop_depth (bb));
       if (flags & TDF_DETAILS)
        {
+         struct function *fun = DECL_STRUCT_FUNCTION (current_function_decl);
          fprintf (outf, ", count " HOST_WIDEST_INT_PRINT_DEC,
                   (HOST_WIDEST_INT) bb->count);
          fprintf (outf, ", freq %i", bb->frequency);
-         if (maybe_hot_bb_p (bb))
+         if (maybe_hot_bb_p (fun, bb))
            fputs (", maybe hot", outf);
-         if (probably_never_executed_bb_p (bb))
+         if (probably_never_executed_bb_p (fun, bb))
            fputs (", probably never executed", outf);
        }
       fputc ('\n', outf);
 
 static inline void
 update_modified_stmt (gimple stmt)
 {
-  if (!ssa_operands_active ())
+  if (!ssa_operands_active (cfun))
     return;
   update_stmt_if_modified (stmt);
 }
 {
   gimple_stmt_iterator gsi;
 
-  if (!ssa_operands_active ())
+  if (!ssa_operands_active (cfun))
     return;
   for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
     update_stmt_if_modified (gsi_stmt (gsi));
 
   tree vdef = gimple_vdef (gs);
   tree vuse = gimple_vuse (gs);
 
-  if (!ssa_operands_active () || !gimple_references_memory_p (gs))
+  if (!ssa_operands_active (DECL_STRUCT_FUNCTION (current_function_decl))
+      || !gimple_references_memory_p (gs))
     return;
 
   if (vdef != NULL_TREE)
       INDENT (curr_indent);
       dump_gimple_stmt (buffer, stmt, curr_indent, flags);
       pp_newline_and_flush (buffer);
-      dump_histograms_for_stmt (cfun, buffer->buffer->stream, stmt);
+      gcc_checking_assert (DECL_STRUCT_FUNCTION (current_function_decl));
+      dump_histograms_for_stmt (DECL_STRUCT_FUNCTION (current_function_decl),
+                               buffer->buffer->stream, stmt);
     }
 
   dump_implicit_edges (buffer, bb, indent, flags);
 
 /* Return TRUE if frequency FREQ is considered to be hot.  */
 
 static inline bool
-maybe_hot_frequency_p (int freq)
+maybe_hot_frequency_p (struct function *fun, int freq)
 {
-  struct cgraph_node *node = cgraph_get_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (fun->decl);
   if (!profile_info || !flag_branch_probabilities)
     {
       if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
       if (node->frequency == NODE_FREQUENCY_HOT)
         return true;
     }
-  if (profile_status == PROFILE_ABSENT)
+  if (profile_status_for_function (fun) == PROFILE_ABSENT)
     return true;
   if (node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-      && freq < (ENTRY_BLOCK_PTR->frequency * 2 / 3))
+      && freq < (ENTRY_BLOCK_PTR_FOR_FUNCTION (fun)->frequency * 2 / 3))
     return false;
-  if (freq < ENTRY_BLOCK_PTR->frequency / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
+  if (freq < (ENTRY_BLOCK_PTR_FOR_FUNCTION (fun)->frequency
+             / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)))
     return false;
   return true;
 }
 /* Return TRUE if frequency FREQ is considered to be hot.  */
 
 static inline bool
-maybe_hot_count_p (gcov_type count)
+maybe_hot_count_p (struct function *fun, gcov_type count)
 {
-  if (profile_status != PROFILE_READ)
+  if (profile_status_for_function (fun) != PROFILE_READ)
     return true;
   /* Code executed at most once is not hot.  */
   if (profile_info->runs >= count)
    for maximal performance.  */
 
 bool
-maybe_hot_bb_p (const_basic_block bb)
+maybe_hot_bb_p (struct function *fun, const_basic_block bb)
 {
-  /* Make sure CFUN exists, for dump_bb_info.  */
-  gcc_assert (cfun);
-  if (profile_status == PROFILE_READ)
-    return maybe_hot_count_p (bb->count);
-  return maybe_hot_frequency_p (bb->frequency);
+  gcc_checking_assert (fun);
+  if (profile_status_for_function (fun) == PROFILE_READ)
+    return maybe_hot_count_p (fun, bb->count);
+  return maybe_hot_frequency_p (fun, bb->frequency);
 }
 
 /* Return true if the call can be hot.  */
 maybe_hot_edge_p (edge e)
 {
   if (profile_status == PROFILE_READ)
-    return maybe_hot_count_p (e->count);
-  return maybe_hot_frequency_p (EDGE_FREQUENCY (e));
+    return maybe_hot_count_p (cfun, e->count);
+  return maybe_hot_frequency_p (cfun, EDGE_FREQUENCY (e));
 }
 
 
 /* Return true in case BB is probably never executed.  */
 
 bool
-probably_never_executed_bb_p (const_basic_block bb)
+probably_never_executed_bb_p (struct function *fun, const_basic_block bb)
 {
-  /* Make sure CFUN exists, for dump_bb_info.  */
-  gcc_assert (cfun);
+  gcc_checking_assert (fun);
   if (profile_info && flag_branch_probabilities)
     return ((bb->count + profile_info->runs / 2) / profile_info->runs) == 0;
   if ((!profile_info || !flag_branch_probabilities)
-      && (cgraph_get_node (current_function_decl)->frequency
+      && (cgraph_get_node (fun->decl)->frequency
          == NODE_FREQUENCY_UNLIKELY_EXECUTED))
     return true;
   return false;
 bool
 optimize_bb_for_size_p (const_basic_block bb)
 {
-  return optimize_function_for_size_p (cfun) || !maybe_hot_bb_p (bb);
+  return optimize_function_for_size_p (cfun) || !maybe_hot_bb_p (cfun, bb);
 }
 
 /* Return TRUE when BB should be optimized for speed.  */
 void
 rtl_profile_for_bb (basic_block bb)
 {
-  crtl->maybe_hot_insn_p = maybe_hot_bb_p (bb);
+  crtl->maybe_hot_insn_p = maybe_hot_bb_p (cfun, bb);
 }
 
 /* Set RTL expansion for edge profile.  */
   node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
   FOR_EACH_BB (bb)
     {
-      if (maybe_hot_bb_p (bb))
+      if (maybe_hot_bb_p (cfun, bb))
        {
          node->frequency = NODE_FREQUENCY_HOT;
          return;
        }
-      if (!probably_never_executed_bb_p (bb))
+      if (!probably_never_executed_bb_p (cfun, bb))
        node->frequency = NODE_FREQUENCY_NORMAL;
     }
 }
 
    */
 
 void
-dump_function_to_file (tree fn, FILE *file, int flags)
+dump_function_to_file (tree fndecl, FILE *file, int flags)
 {
-  tree arg, var;
+  tree arg, var, old_current_fndecl = current_function_decl;
   struct function *dsf;
   bool ignore_topmost_bind = false, any_var = false;
   basic_block bb;
   tree chain;
-  bool tmclone = TREE_CODE (fn) == FUNCTION_DECL && decl_is_tm_clone (fn);
+  bool tmclone = (TREE_CODE (fndecl) == FUNCTION_DECL
+                 && decl_is_tm_clone (fndecl));
+  struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
 
-  fprintf (file, "%s %s(", current_function_name (),
-          tmclone ? "[tm-clone] " : "");
+  current_function_decl = fndecl;
+  fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
 
-  arg = DECL_ARGUMENTS (fn);
+  arg = DECL_ARGUMENTS (fndecl);
   while (arg)
     {
       print_generic_expr (file, TREE_TYPE (arg), dump_flags);
   fprintf (file, ")\n");
 
   if (flags & TDF_VERBOSE)
-    print_node (file, "", fn, 2);
+    print_node (file, "", fndecl, 2);
 
-  dsf = DECL_STRUCT_FUNCTION (fn);
+  dsf = DECL_STRUCT_FUNCTION (fndecl);
   if (dsf && (flags & TDF_EH))
     dump_eh_tree (file, dsf);
 
-  if (flags & TDF_RAW && !gimple_has_body_p (fn))
+  if (flags & TDF_RAW && !gimple_has_body_p (fndecl))
     {
-      dump_node (fn, TDF_SLIM | flags, file);
+      dump_node (fndecl, TDF_SLIM | flags, file);
+      current_function_decl = old_current_fndecl;
       return;
     }
 
-  /* Switch CFUN to point to FN.  */
-  push_cfun (DECL_STRUCT_FUNCTION (fn));
-
   /* When GIMPLE is lowered, the variables are no longer available in
      BIND_EXPRs, so display them separately.  */
-  if (cfun && cfun->decl == fn && (cfun->curr_properties & PROP_gimple_lcf))
+  if (fun && fun->decl == fndecl && (fun->curr_properties & PROP_gimple_lcf))
     {
       unsigned ix;
       ignore_topmost_bind = true;
 
       fprintf (file, "{\n");
-      if (!VEC_empty (tree, cfun->local_decls))
-       FOR_EACH_LOCAL_DECL (cfun, ix, var)
+      if (!VEC_empty (tree, fun->local_decls))
+       FOR_EACH_LOCAL_DECL (fun, ix, var)
          {
            print_generic_decl (file, var, flags);
            if (flags & TDF_VERBOSE)
          }
     }
 
-  if (cfun && cfun->decl == fn && cfun->cfg && basic_block_info)
+  if (fun && fun->decl == fndecl && fun->cfg
+      && basic_block_info_for_function (fun))
     {
       /* If the CFG has been built, emit a CFG-based dump.  */
       if (!ignore_topmost_bind)
        fprintf (file, "{\n");
 
-      if (any_var && n_basic_blocks)
+      if (any_var && n_basic_blocks_for_function (fun))
        fprintf (file, "\n");
 
-      FOR_EACH_BB (bb)
+      FOR_EACH_BB_FN (bb, fun)
        dump_bb (file, bb, 2, flags | TDF_COMMENT);
 
       fprintf (file, "}\n");
     }
-  else if (DECL_SAVED_TREE (fn) == NULL)
+  else if (DECL_SAVED_TREE (fndecl) == NULL)
     {
       /* The function is now in GIMPLE form but the CFG has not been
         built yet.  Emit the single sequence of GIMPLE statements
         that make up its body.  */
-      gimple_seq body = gimple_body (fn);
+      gimple_seq body = gimple_body (fndecl);
 
       if (gimple_seq_first_stmt (body)
          && gimple_seq_first_stmt (body) == gimple_seq_last_stmt (body)
       int indent;
 
       /* Make a tree based dump.  */
-      chain = DECL_SAVED_TREE (fn);
-
+      chain = DECL_SAVED_TREE (fndecl);
       if (chain && TREE_CODE (chain) == BIND_EXPR)
        {
          if (ignore_topmost_bind)
     dump_enumerated_decls (file, flags);
   fprintf (file, "\n\n");
 
-  /* Restore CFUN.  */
-  pop_cfun ();
+  current_function_decl = old_current_fndecl;
 }
 
-
 /* Dump FUNCTION_DECL FN to stderr using FLAGS (see TDF_* in tree.h)  */
 
 DEBUG_FUNCTION void
 
    ssa_op_iter iter;
    use_operand_p use_p;
 
-   if (ssa_operands_active ())
+   if (ssa_operands_active (cfun))
      FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_ALL_USES)
        delink_imm_use (use_p);
 }
 
 /*  Return true if the SSA operands cache is active.  */
 
 bool
-ssa_operands_active (void)
+ssa_operands_active (struct function *fun)
 {
-  /* This function may be invoked from contexts where CFUN is NULL
-     (IPA passes), return false for now.  FIXME: operands may be
-     active in each individual function, maybe this function should
-     take CFUN as a parameter.  */
-  if (cfun == NULL)
+  if (fun == NULL)
     return false;
 
-  return cfun->gimple_df && gimple_ssa_operands (cfun)->ops_active;
+  return fun->gimple_df && gimple_ssa_operands (fun)->ops_active;
 }
 
 
 {
   /* If update_stmt_operands is called before SSA is initialized, do
      nothing.  */
-  if (!ssa_operands_active ())
+  if (!ssa_operands_active (cfun))
     return;
 
   timevar_push (TV_TREE_OPS);
      positions of these two operands in their respective immediate use
      lists by adjusting their use pointer to point to the new
      operand position.  */
-  if (ssa_operands_active () && op0 != op1)
+  if (ssa_operands_active (cfun) && op0 != op1)
     {
       use_optype_p use0, use1, ptr;
       use0 = use1 = NULL;
 
 extern void dump_decl_set (FILE *, bitmap);
 extern void debug_decl_set (bitmap);
 
-extern bool ssa_operands_active (void);
+extern bool ssa_operands_active (struct function *);
 
 extern bool virtual_operand_p (tree);
 extern void unlink_stmt_vdef (gimple);
 
   fini_ssanames ();
 
   /* We no longer maintain the SSA operand cache at this point.  */
-  if (ssa_operands_active ())
+  if (ssa_operands_active (cfun))
     fini_ssa_operands ();
 
   htab_delete (cfun->gimple_df->default_defs);