OSDN Git Service

* cgraph.c (cgraph_create_node): Set node frequency to normal.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 26 Apr 2010 13:33:24 +0000 (13:33 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 26 Apr 2010 13:33:24 +0000 (13:33 +0000)
(cgraph_clone_node): Copy function frequency.
* cgraph.h (node_frequency): New enum
(struct cgraph_node): Add.
* final.c (rest_of_clean_state): Update.
* lto-cgraph.c (lto_output_node): Output node frequency.
(input_overwrite_node): Input node frequency.
* tre-ssa-loop-ivopts (computation_cost): Update.
* lto-streamer-out.c (output_function): Do not output function frequency.
* predict.c (maybe_hot_frequency_p): Update and handle functions executed once.
(cgraph_maybe_hot_edge_p): Likewise; use cgraph frequency instead of
attribute lookup.
(probably_never_executed_bb_p, optimize_function_for_size_p): Update.
(compute_function_frequency): Set noreturn functions to be executed once.
(choose_function_section): Update.
* lto-streamer-in.c (input_function): Do not input function frequency.
* function.c (allocate_struct_function): Do not initialize function frequency.
* function.h (function_frequency): Remove.
(struct function): Remove function frequency.
* ipa-profile.c (CGRAPH_NODE_FREQUENCY): Remove.
(try_update): Update.
* tree-inline.c (initialize_cfun): Do not update function frequency.
* passes.c (pass_init_dump_file): Update.
* i386.c (ix86_compute_frame_layout): Update.
(ix86_pad_returns): Update.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158732 138bc75d-0d04-0410-961f-82ee72b054a4

14 files changed:
gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/config/i386/i386.c
gcc/final.c
gcc/function.c
gcc/function.h
gcc/lto-cgraph.c
gcc/lto-streamer-in.c
gcc/lto-streamer-out.c
gcc/passes.c
gcc/predict.c
gcc/tree-inline.c
gcc/tree-ssa-loop-ivopts.c

index 77d6355..07f7629 100644 (file)
@@ -1,3 +1,31 @@
+2010-04-26  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.c (cgraph_create_node): Set node frequency to normal.
+       (cgraph_clone_node): Copy function frequency.
+       * cgraph.h (node_frequency): New enum
+       (struct cgraph_node): Add.
+       * final.c (rest_of_clean_state): Update.
+       * lto-cgraph.c (lto_output_node): Output node frequency.
+       (input_overwrite_node): Input node frequency.
+       * tre-ssa-loop-ivopts (computation_cost): Update.
+       * lto-streamer-out.c (output_function): Do not output function frequency.
+       * predict.c (maybe_hot_frequency_p): Update and handle functions executed once.
+       (cgraph_maybe_hot_edge_p): Likewise; use cgraph frequency instead of
+       attribute lookup.
+       (probably_never_executed_bb_p, optimize_function_for_size_p): Update.
+       (compute_function_frequency): Set noreturn functions to be executed once.
+       (choose_function_section): Update.
+       * lto-streamer-in.c (input_function): Do not input function frequency.
+       * function.c (allocate_struct_function): Do not initialize function frequency.
+       * function.h (function_frequency): Remove.
+       (struct function): Remove function frequency.
+       * ipa-profile.c (CGRAPH_NODE_FREQUENCY): Remove.
+       (try_update): Update.
+       * tree-inline.c (initialize_cfun): Do not update function frequency.
+       * passes.c (pass_init_dump_file): Update.
+       * i386.c (ix86_compute_frame_layout): Update.
+       (ix86_pad_returns): Update.
+
 2010-04-26  Jie Zhang  <jie@codesourcery.com>
 
        PR tree-optimization/43833
index c5e0f3d..b58d4ee 100644 (file)
@@ -453,6 +453,7 @@ cgraph_create_node (void)
     cgraph_nodes->previous = node;
   node->previous = NULL;
   node->global.estimated_growth = INT_MIN;
+  node->frequency = NODE_FREQUENCY_NORMAL;
   cgraph_nodes = node;
   cgraph_n_nodes++;
   return node;
@@ -1899,6 +1900,7 @@ cgraph_clone_node (struct cgraph_node *n, gcov_type count, int freq,
   new_node->global = n->global;
   new_node->rtl = n->rtl;
   new_node->count = count;
+  new_node->frequency = n->frequency;
   new_node->clone = n->clone;
   new_node->clone.tree_map = 0;
   if (n->count)
index 6bc565a..9b9bf4d 100644 (file)
@@ -175,6 +175,21 @@ struct GTY(()) cgraph_clone_info
   bitmap combined_args_to_skip;
 };
 
+enum node_frequency {
+  /* This function most likely won't be executed at all.
+     (set only when profile feedback is available or via function attribute). */
+  NODE_FREQUENCY_UNLIKELY_EXECUTED,
+  /* For functions that are known to be executed once (i.e. constructors, destructors
+     and main function.  */
+  NODE_FREQUENCY_EXECUTED_ONCE,
+  /* The default value.  */
+  NODE_FREQUENCY_NORMAL,
+  /* Optimize this function hard
+     (set only when profile feedback is available or via function attribute). */
+  NODE_FREQUENCY_HOT
+};
+
+
 /* The cgraph data structure.
    Each function decl has assigned cgraph_node listing callees and callers.  */
 
@@ -267,6 +282,9 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
   /* Set for alias and thunk nodes, same_body points to the node they are alias
      of and they are linked through the next/previous pointers.  */
   unsigned same_body_alias : 1;
+  /* How commonly executed the node is.  Initialized during branch
+     probabilities pass.  */
+  ENUM_BITFIELD (node_frequency) frequency : 2;
 };
 
 typedef struct cgraph_node *cgraph_node_ptr;
index 3e887f8..d13ab18 100644 (file)
@@ -8010,6 +8010,7 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
       && cfun->machine->use_fast_prologue_epilogue_nregs != frame->nregs)
     {
       int count = frame->nregs;
+      struct cgraph_node *node = cgraph_node (current_function_decl);
 
       cfun->machine->use_fast_prologue_epilogue_nregs = count;
       /* The fast prologue uses move instead of push to save registers.  This
@@ -8024,9 +8025,9 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
         slow to use many of them.  */
       if (count)
        count = (count - 1) * FAST_PROLOGUE_INSN_COUNT;
-      if (cfun->function_frequency < FUNCTION_FREQUENCY_NORMAL
+      if (node->frequency < NODE_FREQUENCY_NORMAL
          || (flag_branch_probabilities
-             && cfun->function_frequency < FUNCTION_FREQUENCY_HOT))
+             && node->frequency < NODE_FREQUENCY_HOT))
         cfun->machine->use_fast_prologue_epilogue = false;
       else
         cfun->machine->use_fast_prologue_epilogue
@@ -26706,7 +26707,7 @@ ix86_pad_returns (void)
            replace = true;
          /* Empty functions get branch mispredict even when the jump destination
             is not visible to us.  */
-         if (!prev && cfun->function_frequency > FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
+         if (!prev && !optimize_function_for_size_p (cfun))
            replace = true;
        }
       if (replace)
index e2b7461..5011b6c 100644 (file)
@@ -4374,14 +4374,17 @@ rest_of_clean_state (void)
       else
        {
          const char *aname;
+         struct cgraph_node *node = cgraph_node (current_function_decl);
 
          aname = (IDENTIFIER_POINTER
                   (DECL_ASSEMBLER_NAME (current_function_decl)));
          fprintf (final_output, "\n;; Function (%s) %s\n\n", aname,
-            cfun->function_frequency == FUNCTION_FREQUENCY_HOT
+            node->frequency == NODE_FREQUENCY_HOT
             ? " (hot)"
-            : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED
+            : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
             ? " (unlikely executed)"
+            : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
+            ? " (executed once)"
             : "");
 
          flag_dump_noaddr = flag_dump_unnumbered = 1;
index f78bc98..949480c 100644 (file)
@@ -4115,8 +4115,6 @@ allocate_struct_function (tree fndecl, bool abstract_p)
 
   cfun = GGC_CNEW (struct function);
 
-  cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL;
-
   init_eh_for_function ();
 
   if (init_machine_status)
index fb2965a..e5e0338 100644 (file)
@@ -176,17 +176,6 @@ typedef struct ipa_opt_pass_d *ipa_opt_pass;
 DEF_VEC_P(ipa_opt_pass);
 DEF_VEC_ALLOC_P(ipa_opt_pass,heap);
 
-enum function_frequency {
-  /* This function most likely won't be executed at all.
-     (set only when profile feedback is available or via function attribute). */
-  FUNCTION_FREQUENCY_UNLIKELY_EXECUTED,
-  /* The default value.  */
-  FUNCTION_FREQUENCY_NORMAL,
-  /* Optimize this function hard
-     (set only when profile feedback is available or via function attribute). */
-  FUNCTION_FREQUENCY_HOT
-};
-
 struct GTY(()) varasm_status {
   /* If we're using a per-function constant pool, this is it.  */
   struct rtx_constant_pool *pool;
@@ -538,10 +527,6 @@ struct GTY(()) function {
      function.  */
   unsigned int va_list_fpr_size : 8;
 
-  /* How commonly executed the function is.  Initialized during branch
-     probabilities pass.  */
-  ENUM_BITFIELD (function_frequency) function_frequency : 2;
-
   /* Nonzero if function being compiled can call setjmp.  */
   unsigned int calls_setjmp : 1;
 
index cb87143..6f22968 100644 (file)
@@ -286,6 +286,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   bp_pack_value (bp, node->process, 1);
   bp_pack_value (bp, node->alias, 1);
   bp_pack_value (bp, node->finalized_by_frontend, 1);
+  bp_pack_value (bp, node->frequency, 2);
   lto_output_bitpack (ob->main_stream, bp);
   bitpack_delete (bp);
 
@@ -544,6 +545,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
   node->process = bp_unpack_value (bp, 1);
   node->alias = bp_unpack_value (bp, 1);
   node->finalized_by_frontend = bp_unpack_value (bp, 1);
+  node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
 }
 
 
index 6afad5b..4f9fca3 100644 (file)
@@ -1314,7 +1314,6 @@ input_function (tree fn_decl, struct data_in *data_in,
   fn->has_nonlocal_label = bp_unpack_value (bp, 1);
   fn->calls_alloca = bp_unpack_value (bp, 1);
   fn->calls_setjmp = bp_unpack_value (bp, 1);
-  fn->function_frequency = (enum function_frequency) bp_unpack_value (bp, 2);
   fn->va_list_fpr_size = bp_unpack_value (bp, 8);
   fn->va_list_gpr_size = bp_unpack_value (bp, 8);
   bitpack_delete (bp);
index c922025..e9ae494 100644 (file)
@@ -1866,7 +1866,6 @@ output_function (struct cgraph_node *node)
   bp_pack_value (bp, fn->has_nonlocal_label, 1);
   bp_pack_value (bp, fn->calls_alloca, 1);
   bp_pack_value (bp, fn->calls_setjmp, 1);
-  bp_pack_value (bp, fn->function_frequency, 2);
   bp_pack_value (bp, fn->va_list_fpr_size, 8);
   bp_pack_value (bp, fn->va_list_gpr_size, 8);
   lto_output_bitpack (ob->main_stream, bp);
index a6e5af5..e503dc6 100644 (file)
@@ -1361,14 +1361,17 @@ pass_init_dump_file (struct opt_pass *pass)
       if (dump_file && current_function_decl)
        {
          const char *dname, *aname;
+         struct cgraph_node *node = cgraph_node (current_function_decl);
          dname = lang_hooks.decl_printable_name (current_function_decl, 2);
          aname = (IDENTIFIER_POINTER
                   (DECL_ASSEMBLER_NAME (current_function_decl)));
          fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname,
-            cfun->function_frequency == FUNCTION_FREQUENCY_HOT
+            node->frequency == NODE_FREQUENCY_HOT
             ? " (hot)"
-            : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED
+            : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
             ? " (unlikely executed)"
+            : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
+            ? " (executed once)"
             : "");
        }
       return initializing_dump;
index eb5ddef..29e0e2f 100644 (file)
@@ -113,15 +113,19 @@ static const struct predictor_info predictor_info[]= {
 static inline bool
 maybe_hot_frequency_p (int freq)
 {
+  struct cgraph_node *node = cgraph_node (current_function_decl);
   if (!profile_info || !flag_branch_probabilities)
     {
-      if (cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
+      if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
         return false;
-      if (cfun->function_frequency == FUNCTION_FREQUENCY_HOT)
+      if (node->frequency == NODE_FREQUENCY_HOT)
         return true;
     }
   if (profile_status == PROFILE_ABSENT)
     return true;
+  if (node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
+      && freq <= (ENTRY_BLOCK_PTR->frequency * 2 / 3))
+    return false;
   if (freq < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
     return false;
   return true;
@@ -161,11 +165,16 @@ cgraph_maybe_hot_edge_p (struct cgraph_edge *edge)
       && (edge->count
          <= profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
     return false;
-  if (lookup_attribute ("cold", DECL_ATTRIBUTES (edge->callee->decl))
-      || lookup_attribute ("cold", DECL_ATTRIBUTES (edge->caller->decl)))
+  if (edge->caller->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
+      || edge->callee->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
+    return false;
+  if (optimize_size)
     return false;
-  if (lookup_attribute ("hot", DECL_ATTRIBUTES (edge->caller->decl)))
+  if (edge->caller->frequency == NODE_FREQUENCY_HOT)
     return true;
+  if (edge->caller->frequency == NODE_FREQUENCY_EXECUTED_ONCE
+      && edge->frequency < CGRAPH_FREQ_BASE * 3 / 2)
+    return false;
   if (flag_guess_branch_prob
       && edge->frequency <= (CGRAPH_FREQ_BASE
                             / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)))
@@ -191,7 +200,7 @@ probably_never_executed_bb_p (const_basic_block bb)
   if (profile_info && flag_branch_probabilities)
     return ((bb->count + profile_info->runs / 2) / profile_info->runs) == 0;
   if ((!profile_info || !flag_branch_probabilities)
-      && cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
+      && cgraph_node (current_function_decl)->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
     return true;
   return false;
 }
@@ -202,8 +211,9 @@ bool
 optimize_function_for_size_p (struct function *fun)
 {
   return (optimize_size
-         || (fun && (fun->function_frequency
-                     == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)));
+         || (fun && fun->decl
+             && (cgraph_node (fun->decl)->frequency
+                 == NODE_FREQUENCY_UNLIKELY_EXECUTED)));
 }
 
 /* Return true when current function should always be optimized for speed.  */
@@ -2148,27 +2158,36 @@ void
 compute_function_frequency (void)
 {
   basic_block bb;
+  struct cgraph_node *node = cgraph_node (current_function_decl);
 
   if (!profile_info || !flag_branch_probabilities)
     {
+      int flags = flags_from_decl_or_type (current_function_decl);
       if (lookup_attribute ("cold", DECL_ATTRIBUTES (current_function_decl))
          != NULL)
-        cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
+        node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
       else if (lookup_attribute ("hot", DECL_ATTRIBUTES (current_function_decl))
               != NULL)
-        cfun->function_frequency = FUNCTION_FREQUENCY_HOT;
+        node->frequency = NODE_FREQUENCY_HOT;
+      else if (flags & ECF_NORETURN)
+        node->frequency = NODE_FREQUENCY_EXECUTED_ONCE;
+      else if (MAIN_NAME_P (DECL_NAME (current_function_decl)))
+        node->frequency = NODE_FREQUENCY_EXECUTED_ONCE;
+      else if (DECL_STATIC_CONSTRUCTOR (current_function_decl)
+              || DECL_STATIC_DESTRUCTOR (current_function_decl))
+        node->frequency = NODE_FREQUENCY_EXECUTED_ONCE;
       return;
     }
-  cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
+  node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
   FOR_EACH_BB (bb)
     {
       if (maybe_hot_bb_p (bb))
        {
-         cfun->function_frequency = FUNCTION_FREQUENCY_HOT;
+         node->frequency = NODE_FREQUENCY_HOT;
          return;
        }
       if (!probably_never_executed_bb_p (bb))
-       cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL;
+       node->frequency = NODE_FREQUENCY_NORMAL;
     }
 }
 
@@ -2176,6 +2195,7 @@ compute_function_frequency (void)
 static void
 choose_function_section (void)
 {
+  struct cgraph_node *node = cgraph_node (current_function_decl);
   if (DECL_SECTION_NAME (current_function_decl)
       || !targetm.have_named_sections
       /* Theoretically we can split the gnu.linkonce text section too,
@@ -2191,10 +2211,10 @@ choose_function_section (void)
   if (flag_reorder_blocks_and_partition)
     return;
 
-  if (cfun->function_frequency == FUNCTION_FREQUENCY_HOT)
+  if (node->frequency == NODE_FREQUENCY_HOT)
     DECL_SECTION_NAME (current_function_decl) =
       build_string (strlen (HOT_TEXT_SECTION_NAME), HOT_TEXT_SECTION_NAME);
-  if (cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
+  if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
     DECL_SECTION_NAME (current_function_decl) =
       build_string (strlen (UNLIKELY_EXECUTED_TEXT_SECTION_NAME),
                    UNLIKELY_EXECUTED_TEXT_SECTION_NAME);
index 59661a7..0c1293e 100644 (file)
@@ -2014,7 +2014,6 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count)
   cfun->last_verified = src_cfun->last_verified;
   cfun->va_list_gpr_size = src_cfun->va_list_gpr_size;
   cfun->va_list_fpr_size = src_cfun->va_list_fpr_size;
-  cfun->function_frequency = src_cfun->function_frequency;
   cfun->has_nonlocal_label = src_cfun->has_nonlocal_label;
   cfun->stdarg = src_cfun->stdarg;
   cfun->dont_save_pending_sizes_p = src_cfun->dont_save_pending_sizes_p;
index f6db241..a7a9e25 100644 (file)
@@ -2738,9 +2738,10 @@ computation_cost (tree expr, bool speed)
   unsigned cost;
   /* Avoid using hard regs in ways which may be unsupported.  */
   int regno = LAST_VIRTUAL_REGISTER + 1;
-  enum function_frequency real_frequency = cfun->function_frequency;
+  struct cgraph_node *node = cgraph_node (current_function_decl);
+  enum node_frequency real_frequency = node->frequency;
 
-  cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL;
+  node->frequency = NODE_FREQUENCY_NORMAL;
   crtl->maybe_hot_insn_p = speed;
   walk_tree (&expr, prepare_decl_rtl, &regno, NULL);
   start_sequence ();
@@ -2748,7 +2749,7 @@ computation_cost (tree expr, bool speed)
   seq = get_insns ();
   end_sequence ();
   default_rtl_profile ();
-  cfun->function_frequency = real_frequency;
+  node->frequency = real_frequency;
 
   cost = seq_cost (seq, speed);
   if (MEM_P (rslt))