aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2005-05-19 12:38:42 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2005-05-19 10:38:42 +0000
commite42922b1ae4c3da94882d3a92ce978a0db123064 (patch)
tree1d011084a5002e1aadab35d8ef841e441fb68211 /gcc
parenteef16504e21f8d504b6a648cf73955e977d5adf6 (diff)
downloadgcc-e42922b1ae4c3da94882d3a92ce978a0db123064.zip
gcc-e42922b1ae4c3da94882d3a92ce978a0db123064.tar.gz
gcc-e42922b1ae4c3da94882d3a92ce978a0db123064.tar.bz2
basic-block.h (REG_BR_PROB_BASE): Define.
* basic-block.h (REG_BR_PROB_BASE): Define. * cgraph.c (cgraph_create_edge): Initialize loop_nest and count. (dump_cgraph_node): Dump count. (cgraph_clone_edge): Rescale counts. (cgraph_clone_node): Likewise. * cgraph.h: Include basic-block.h (cgraph_node): Add count. (cgraph_edge): Add count and loop_nest. (cgraph_node, cgraph_edge, cgraph_clone_edge, cgraph_clone_node): Update prototypes. * cgraphunit.c: Kill now redundant inlining comment. (cgraph_create_edges): Make static, maintain current basic block; fix pasto. (record_call_1): Fill in new fields. * ipa-inline.c (cgraph_clone_inlined_nodes): Update call of cgraph_clone_node. (cgraph_decide_recursive_inlining): Likewise. * rtl.h (REG_BR_PROB_BASE): Kill. * tree-inline.c (copy_body_r): Update call of cgraph_clone_edge. (expand_call_inline): Update call of cgraph_create_edge. * tree-optimize.c (tree_rest_of_compilation): Likewise. From-SVN: r99976
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/basic-block.h3
-rw-r--r--gcc/cgraph.c34
-rw-r--r--gcc/cgraph.h22
-rw-r--r--gcc/cgraphunit.c47
-rw-r--r--gcc/ipa-inline.c4
-rw-r--r--gcc/rtl.h3
-rw-r--r--gcc/tree-inline.c6
-rw-r--r--gcc/tree-optimize.c2
9 files changed, 89 insertions, 56 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ac2ac51..51df4dc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,27 @@
+2005-05-19 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h (REG_BR_PROB_BASE): Define.
+ * cgraph.c (cgraph_create_edge): Initialize loop_nest and count.
+ (dump_cgraph_node): Dump count.
+ (cgraph_clone_edge): Rescale counts.
+ (cgraph_clone_node): Likewise.
+ * cgraph.h: Include basic-block.h
+ (cgraph_node): Add count.
+ (cgraph_edge): Add count and loop_nest.
+ (cgraph_node, cgraph_edge, cgraph_clone_edge, cgraph_clone_node):
+ Update prototypes.
+ * cgraphunit.c: Kill now redundant inlining comment.
+ (cgraph_create_edges): Make static, maintain current basic block;
+ fix pasto.
+ (record_call_1): Fill in new fields.
+ * ipa-inline.c (cgraph_clone_inlined_nodes): Update call of
+ cgraph_clone_node.
+ (cgraph_decide_recursive_inlining): Likewise.
+ * rtl.h (REG_BR_PROB_BASE): Kill.
+ * tree-inline.c (copy_body_r): Update call of cgraph_clone_edge.
+ (expand_call_inline): Update call of cgraph_create_edge.
+ * tree-optimize.c (tree_rest_of_compilation): Likewise.
+
2005-05-19 Nick Clifton <nickc@redhat.com>
* config/rs6000/eabispe.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Use the
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 5565053..4deeb89 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -555,6 +555,9 @@ struct edge_list
edge *index_to_edge;
};
+/* The base value for branch probability notes and edge probabilities. */
+#define REG_BR_PROB_BASE 10000
+
/* This is the value which indicates no edge is present. */
#define EDGE_INDEX_NO_EDGE -1
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index adef0bd..c2509ff 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -275,7 +275,7 @@ cgraph_edge (struct cgraph_node *node, tree call_expr)
struct cgraph_edge *
cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee,
- tree call_expr)
+ tree call_expr, gcov_type count, int nest)
{
struct cgraph_edge *edge = ggc_alloc (sizeof (struct cgraph_edge));
#ifdef ENABLE_CHECKING
@@ -312,6 +312,8 @@ cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee,
caller->callees->prev_callee = edge;
caller->callees = edge;
callee->callers = edge;
+ edge->count = count;
+ edge->loop_nest = nest;
return edge;
}
@@ -559,6 +561,9 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, " (inline copy in %s/%i)",
cgraph_node_name (node->global.inlined_to),
node->global.inlined_to->uid);
+ if (node->count)
+ fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x",
+ (HOST_WIDEST_INT)node->count);
if (node->local.self_insns)
fprintf (f, " %i insns", node->local.self_insns);
if (node->global.insns && node->global.insns != node->local.self_insns)
@@ -587,6 +592,9 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
{
fprintf (f, "%s/%i ", cgraph_node_name (edge->caller),
edge->caller->uid);
+ if (edge->count)
+ fprintf (f, "("HOST_WIDEST_INT_PRINT_DEC"x) ",
+ (HOST_WIDEST_INT)edge->count);
if (!edge->inline_failed)
fprintf(f, "(inlined) ");
}
@@ -829,20 +837,28 @@ cgraph_function_possibly_inlined_p (tree decl)
/* Create clone of E in the node N represented by CALL_EXPR the callgraph. */
struct cgraph_edge *
-cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n, tree call_expr)
+cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
+ tree call_expr, int count_scale, int loop_nest)
{
- struct cgraph_edge *new = cgraph_create_edge (n, e->callee, call_expr);
+ struct cgraph_edge *new;
+
+ new = cgraph_create_edge (n, e->callee, call_expr,
+ e->count * count_scale / REG_BR_PROB_BASE,
+ e->loop_nest + loop_nest);
new->inline_failed = e->inline_failed;
+ e->count -= new->count;
return new;
}
-/* Create node representing clone of N. */
+/* Create node representing clone of N executed COUNT times. Decrease
+ the execution counts from original node too. */
struct cgraph_node *
-cgraph_clone_node (struct cgraph_node *n)
+cgraph_clone_node (struct cgraph_node *n, gcov_type count, int loop_nest)
{
struct cgraph_node *new = cgraph_create_node ();
struct cgraph_edge *e;
+ int count_scale;
new->decl = n->decl;
new->origin = n->origin;
@@ -855,9 +871,15 @@ cgraph_clone_node (struct cgraph_node *n)
new->local = n->local;
new->global = n->global;
new->rtl = n->rtl;
+ new->count = count;
+ if (n->count)
+ count_scale = new->count * REG_BR_PROB_BASE / n->count;
+ else
+ count_scale = 0;
+ n->count -= count;
for (e = n->callees;e; e=e->next_callee)
- cgraph_clone_edge (e, new, e->call_expr);
+ cgraph_clone_edge (e, new, e->call_expr, count_scale, loop_nest);
new->next_clone = n->next_clone;
new->prev_clone = n;
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 6f3864c..294b690 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -22,6 +22,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#ifndef GCC_CGRAPH_H
#define GCC_CGRAPH_H
#include "tree.h"
+#include "basic-block.h"
/* Information about the function collected locally.
Available after function is analyzed. */
@@ -109,6 +110,8 @@ struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous")))
struct cgraph_global_info global;
struct cgraph_rtl_info rtl;
+ /* Expected number of executions: calculated in profile.c. */
+ gcov_type count;
/* Unique id of the node. */
int uid;
/* Set when function must be output - it is externally visible
@@ -141,6 +144,10 @@ struct cgraph_edge GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_call
/* When NULL, inline this call. When non-NULL, points to the explanation
why function was not inlined. */
const char *inline_failed;
+ /* Expected number of executions: calculated in profile.c. */
+ gcov_type count;
+ /* Depth of loop nest, 1 means no loop nest. */
+ int loop_nest;
};
/* The cgraph_varpool data structure.
@@ -190,25 +197,25 @@ void cgraph_remove_node (struct cgraph_node *);
void cgraph_node_remove_callees (struct cgraph_node *node);
struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
struct cgraph_node *,
- tree);
-struct cgraph_node *cgraph_node (tree decl);
+ tree, gcov_type, int);
+struct cgraph_node *cgraph_node (tree);
struct cgraph_node *cgraph_node_for_asm (tree asmname);
-struct cgraph_edge *cgraph_edge (struct cgraph_node *, tree call_expr);
+struct cgraph_edge *cgraph_edge (struct cgraph_node *, tree);
struct cgraph_local_info *cgraph_local_info (tree);
struct cgraph_global_info *cgraph_global_info (tree);
struct cgraph_rtl_info *cgraph_rtl_info (tree);
const char * cgraph_node_name (struct cgraph_node *);
-struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *, struct cgraph_node *, tree);
-struct cgraph_node * cgraph_clone_node (struct cgraph_node *);
+struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *, struct cgraph_node *, tree, int, int);
+struct cgraph_node * cgraph_clone_node (struct cgraph_node *, gcov_type, int);
-struct cgraph_varpool_node *cgraph_varpool_node (tree decl);
+struct cgraph_varpool_node *cgraph_varpool_node (tree);
struct cgraph_varpool_node *cgraph_varpool_node_for_asm (tree asmname);
void cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *);
void cgraph_varpool_finalize_decl (tree);
void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
bool cgraph_function_possibly_inlined_p (tree);
-void cgraph_unnest_node (struct cgraph_node *node);
+void cgraph_unnest_node (struct cgraph_node *);
void cgraph_varpool_enqueue_needed_node (struct cgraph_varpool_node *);
void cgraph_varpool_reset_queue (void);
bool decide_is_variable_needed (struct cgraph_varpool_node *, tree);
@@ -219,7 +226,6 @@ bool cgraph_varpool_assemble_pending_decls (void);
void cgraph_finalize_function (tree, bool);
void cgraph_lower_function (struct cgraph_node *);
void cgraph_finalize_compilation_unit (void);
-void cgraph_create_edges (struct cgraph_node *, tree);
void cgraph_optimize (void);
void cgraph_mark_needed_node (struct cgraph_node *);
void cgraph_mark_reachable_node (struct cgraph_node *);
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 548a5fcb..14eb46b 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -136,33 +136,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
decision on whether function is needed is made more conservative so
uninlininable static functions are needed too. During the call-graph
construction the edge destinations are not marked as reachable and it
- is completely relied upn assemble_variable to mark them.
-
- Inlining decision heuristics
- ??? Move this to separate file after tree-ssa merge.
-
- We separate inlining decisions from the inliner itself and store it
- inside callgraph as so called inline plan. Refer to cgraph.c
- documentation about particular representation of inline plans in the
- callgraph
-
- The implementation of particular heuristics is separated from
- the rest of code to make it easier to replace it with more complicated
- implementation in the future. The rest of inlining code acts as a
- library aimed to modify the callgraph and verify that the parameters
- on code size growth fits.
-
- To mark given call inline, use cgraph_mark_inline function, the
- verification is performed by cgraph_default_inline_p and
- cgraph_check_inline_limits.
-
- The heuristics implements simple knapsack style algorithm ordering
- all functions by their "profitability" (estimated by code size growth)
- and inlining them in priority order.
-
- cgraph_decide_inlining implements heuristics taking whole callgraph
- into account, while cgraph_decide_inlining_incrementally considers
- only one function at a time and is used in non-unit-at-a-time mode. */
+ is completely relied upn assemble_variable to mark them. */
#include "config.h"
@@ -198,6 +172,7 @@ static void cgraph_expand_function (struct cgraph_node *);
static tree record_call_1 (tree *, int *, void *);
static void cgraph_mark_local_functions (void);
static void cgraph_analyze_function (struct cgraph_node *node);
+static void cgraph_create_edges (struct cgraph_node *node, tree body);
/* Records tree nodes seen in cgraph_create_edges. Simply using
walk_tree_without_duplicates doesn't guarantee each node is visited
@@ -460,6 +435,9 @@ cgraph_finalize_function (tree decl, bool nested)
do_warn_unused_parameter (decl);
}
+/* Used only while constructing the callgraph. */
+static basic_block current_basic_block;
+
void
cgraph_lower_function (struct cgraph_node *node)
{
@@ -469,7 +447,6 @@ cgraph_lower_function (struct cgraph_node *node)
node->lowered = true;
}
-
/* Walk tree and record all calls. Called via walk_tree. */
static tree
record_call_1 (tree *tp, int *walk_subtrees, void *data)
@@ -508,7 +485,9 @@ record_call_1 (tree *tp, int *walk_subtrees, void *data)
tree decl = get_callee_fndecl (*tp);
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
{
- cgraph_create_edge (data, cgraph_node (decl), *tp);
+ cgraph_create_edge (data, cgraph_node (decl), *tp,
+ current_basic_block->count,
+ current_basic_block->loop_depth);
/* When we see a function call, we don't want to look at the
function reference in the ADDR_EXPR that is hanging from
@@ -543,24 +522,25 @@ record_call_1 (tree *tp, int *walk_subtrees, void *data)
/* Create cgraph edges for function calls inside BODY from NODE. */
-void
+static void
cgraph_create_edges (struct cgraph_node *node, tree body)
{
/* The nodes we're interested in are never shared, so walk
the tree ignoring duplicates. */
visited_nodes = pointer_set_create ();
+ gcc_assert (current_basic_block == NULL);
if (TREE_CODE (body) == FUNCTION_DECL)
{
struct function *this_cfun = DECL_STRUCT_FUNCTION (body);
- basic_block this_block;
block_stmt_iterator bsi;
tree step;
/* Reach the trees by walking over the CFG, and note the
enclosing basic-blocks in the call edges. */
- FOR_EACH_BB_FN (this_block, this_cfun)
- for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
+ FOR_EACH_BB_FN (current_basic_block, this_cfun)
+ for (bsi = bsi_start (current_basic_block); !bsi_end_p (bsi); bsi_next (&bsi))
walk_tree (bsi_stmt_ptr (bsi), record_call_1, node, visited_nodes);
+ current_basic_block = NULL;
/* Walk over any private statics that may take addresses of functions. */
if (TREE_CODE (DECL_INITIAL (body)) == BLOCK)
@@ -586,7 +566,6 @@ cgraph_create_edges (struct cgraph_node *node, tree body)
else
walk_tree (&body, record_call_1, node, visited_nodes);
- walk_tree (&body, record_call_1, node, visited_nodes);
pointer_set_destroy (visited_nodes);
visited_nodes = NULL;
}
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index f1236ea..79150d2 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -123,7 +123,7 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate)
}
else if (duplicate)
{
- n = cgraph_clone_node (e->callee);
+ n = cgraph_clone_node (e->callee, e->count, e->loop_nest);
cgraph_redirect_edge_callee (e, n);
}
@@ -369,7 +369,7 @@ cgraph_decide_recursive_inlining (struct cgraph_node *node)
cgraph_node_name (node));
/* We need original clone to copy around. */
- master_clone = cgraph_clone_node (node);
+ master_clone = cgraph_clone_node (node, 0, 1);
master_clone->needed = true;
for (e = master_clone->callees; e; e = e->next_callee)
if (!e->inline_failed)
diff --git a/gcc/rtl.h b/gcc/rtl.h
index c162393..2eb5d9c 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -706,9 +706,6 @@ enum reg_note
REG_NOTE_MAX
};
-/* The base value for branch probability notes. */
-#define REG_BR_PROB_BASE 10000
-
/* Define macros to extract and insert the reg-note kind in an EXPR_LIST. */
#define REG_NOTE_KIND(LINK) ((enum reg_note) GET_MODE (LINK))
#define PUT_REG_NOTE_KIND(LINK, KIND) \
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index d9654f4..118f493 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -656,7 +656,8 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
associate callgraph nodes. */
edge = cgraph_edge (id->current_node, old_node);
if (edge)
- cgraph_clone_edge (edge, id->node, *tp);
+ cgraph_clone_edge (edge, id->node, *tp,
+ REG_BR_PROB_BASE, 1);
}
}
else if (TREE_CODE (*tp) == RESX_EXPR && id->eh_region_offset)
@@ -1922,7 +1923,8 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
constant propagating arguments. In all other cases we hit a bug
(incorrect node sharing is most common reason for missing edges. */
gcc_assert (dest->needed || !flag_unit_at_a_time);
- cgraph_create_edge (id->node, dest, t)->inline_failed
+ cgraph_create_edge (id->node, dest, t,
+ bb->count, bb->loop_depth)->inline_failed
= N_("originally indirect function call not considered for inlining");
goto egress;
}
diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c
index 109c5bc..7c9beb8 100644
--- a/gcc/tree-optimize.c
+++ b/gcc/tree-optimize.c
@@ -741,7 +741,7 @@ tree_rest_of_compilation (tree fndecl)
{
struct cgraph_edge *e;
- saved_node = cgraph_clone_node (node);
+ saved_node = cgraph_clone_node (node, node->count, 1);
for (e = saved_node->callees; e; e = e->next_callee)
if (!e->inline_failed)
cgraph_clone_inlined_nodes (e, true);