aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2010-04-26 15:33:24 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2010-04-26 13:33:24 +0000
commit5fefcf92fa6b75486291d2a898f9a0e4d541cf6c (patch)
tree23c770f34cffee8dfe268868d96f062a649cf2fd
parent21aac88050970dff5e2632aa355caed48eee894c (diff)
downloadgcc-5fefcf92fa6b75486291d2a898f9a0e4d541cf6c.zip
gcc-5fefcf92fa6b75486291d2a898f9a0e4d541cf6c.tar.gz
gcc-5fefcf92fa6b75486291d2a898f9a0e4d541cf6c.tar.bz2
cgraph.c (cgraph_create_node): Set node frequency to normal.
* 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. From-SVN: r158732
-rw-r--r--gcc/ChangeLog28
-rw-r--r--gcc/cgraph.c2
-rw-r--r--gcc/cgraph.h18
-rw-r--r--gcc/config/i386/i386.c7
-rw-r--r--gcc/final.c7
-rw-r--r--gcc/function.c2
-rw-r--r--gcc/function.h15
-rw-r--r--gcc/lto-cgraph.c2
-rw-r--r--gcc/lto-streamer-in.c1
-rw-r--r--gcc/lto-streamer-out.c1
-rw-r--r--gcc/passes.c7
-rw-r--r--gcc/predict.c50
-rw-r--r--gcc/tree-inline.c1
-rw-r--r--gcc/tree-ssa-loop-ivopts.c7
14 files changed, 103 insertions, 45 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 77d6355..07f7629 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index c5e0f3d..b58d4ee 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -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)
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 6bc565a..9b9bf4d 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -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;
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 3e887f8..d13ab18 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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)
diff --git a/gcc/final.c b/gcc/final.c
index e2b7461..5011b6c 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -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;
diff --git a/gcc/function.c b/gcc/function.c
index f78bc98..949480c 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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)
diff --git a/gcc/function.h b/gcc/function.h
index fb2965a..e5e0338 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -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;
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index cb87143..6f22968 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -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);
}
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 6afad5b..4f9fca3 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -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);
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index c922025..e9ae494 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -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);
diff --git a/gcc/passes.c b/gcc/passes.c
index a6e5af5..e503dc6 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -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;
diff --git a/gcc/predict.c b/gcc/predict.c
index eb5ddef..29e0e2f 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -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);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 59661a7..0c1293e 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -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;
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index f6db241..a7a9e25 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -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))