diff options
author | Zdenek Dvorak <dvorakz@suse.cz> | 2007-01-28 18:40:38 +0100 |
---|---|---|
committer | Zdenek Dvorak <rakdver@gcc.gnu.org> | 2007-01-28 17:40:38 +0000 |
commit | 7f9bc51b091441d6f9484c62d210d4fc724b376b (patch) | |
tree | c62392cb24f6c73aa4b1c6e48f7355a4012a7a9b /gcc/tree-inline.c | |
parent | b39c6706458c006734d1a02c1a180b00d88182a5 (diff) | |
download | gcc-7f9bc51b091441d6f9484c62d210d4fc724b376b.zip gcc-7f9bc51b091441d6f9484c62d210d4fc724b376b.tar.gz gcc-7f9bc51b091441d6f9484c62d210d4fc724b376b.tar.bz2 |
tree-ssa-loop-unswitch.c: Include tree-inline.h.
* tree-ssa-loop-unswitch.c: Include tree-inline.h.
(tree_unswitch_single_loop): Pass eni_size_weights to
tree_num_loop_insns.
* tree-ssa-loop-manip.c: Include tree-inline.h.
(can_unroll_loop_p): Pass eni_size_weights to
tree_num_loop_insns.
* tree-ssa-loop-ch.c (should_duplicate_loop_header_p):
Pass eni_size_weights to estimate_num_insns.
* tree.h (init_inline_once): Export.
* toplev.c (backend_init): Call init_inline_once.
* cgraphunit.c (cgraph_process_new_functions,
cgraph_analyze_function): Pass eni_inlining_weights to
estimate_num_insns.
* ipa-inline.c (compute_inline_parameters): Ditto.
* tree-ssa-loop-ivcanon.c (tree_num_loop_insns): Pass weights
to estimate_num_insns.
(try_unroll_loop_completely): Pass eni_size_weights to
tree_num_loop_insns.
* tree-eh.c (decide_copy_try_finally): Pass eni_size_weights
ot estimate_num_insns.
* tree-ssa-loop-prefetch.c: Include tree-inline.h.
(loop_prefetch_arrays): Pass eni_time_weights to tree_num_loop_insns.
* tree-inline.c (eni_inlining_weights, eni_size_weights,
eni_time_weights): New variables.
(init_inline_once): Initialize them.
(struct eni_data): Mew.
(estimate_num_insns_1, estimate_num_insns): Use weights.
* tree-inline.h (struct eni_weights_d): New.
(eni_inlining_weights, eni_size_weights, eni_time_weights): Declare.
(estimate_num_insns): Declaration changed.
* cfgloop.h (tree_num_loop_insns): Declaration changed.
* Makefile.in (tree-ssa-loop-unswitch.o, tree-ssa-loop-prefetch.o,
tree-ssa-loop-manip.o): Add TREE_INLINE_H dependency.
* gcc.dg/tree-ssa/loop-23.c: New test.
From-SVN: r121260
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r-- | gcc/tree-inline.c | 97 |
1 files changed, 81 insertions, 16 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 813f18d..d68190f 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -107,6 +107,21 @@ int flag_inline_trees = 0; o Provide heuristics to clamp inlining of recursive template calls? */ + +/* Weights that estimate_num_insns uses for heuristics in inlining. */ + +eni_weights eni_inlining_weights; + +/* Weights that estimate_num_insns uses to estimate the size of the + produced code. */ + +eni_weights eni_size_weights; + +/* Weights that estimate_num_insns uses to estimate the time necessary + to execute the produced code. */ + +eni_weights eni_time_weights; + /* Prototypes. */ static tree declare_return_variable (copy_body_data *, tree, tree, tree *); @@ -1904,14 +1919,26 @@ estimate_move_cost (tree type) return ((size + MOVE_MAX_PIECES - 1) / MOVE_MAX_PIECES); } +/* Arguments for estimate_num_insns_1. */ + +struct eni_data +{ + /* Used to return the number of insns. */ + int count; + + /* Weights of various constructs. */ + eni_weights *weights; +}; + /* Used by estimate_num_insns. Estimate number of instructions seen by given statement. */ static tree estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) { - int *count = (int *) data; + struct eni_data *d = data; tree x = *tp; + unsigned cost; if (IS_TYPE_OR_DECL_P (x)) { @@ -2026,7 +2053,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) /* Otherwise it's a store, so fall through to compute the move cost. */ case CONSTRUCTOR: - *count += estimate_move_cost (TREE_TYPE (x)); + d->count += estimate_move_cost (TREE_TYPE (x)); break; /* Assign cost of 1 to usual operations. @@ -2090,8 +2117,6 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) case POSTDECREMENT_EXPR: case POSTINCREMENT_EXPR: - case SWITCH_EXPR: - case ASM_EXPR: case REALIGN_LOAD_EXPR: @@ -2116,7 +2141,13 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) case VEC_INTERLEAVE_LOW_EXPR: case RESX_EXPR: - *count += 1; + d->count += 1; + break; + + case SWITCH_EXPR: + /* TODO: Cost of a switch should be derived from the number of + branches. */ + d->count += d->weights->switch_cost; break; /* Few special cases of expensive operations. This is useful @@ -2131,13 +2162,14 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) case FLOOR_MOD_EXPR: case ROUND_MOD_EXPR: case RDIV_EXPR: - *count += 10; + d->count += d->weights->div_mod_cost; break; case CALL_EXPR: { tree decl = get_callee_fndecl (x); tree arg; + cost = d->weights->call_cost; if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) switch (DECL_FUNCTION_CODE (decl)) { @@ -2146,6 +2178,10 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) return NULL_TREE; case BUILT_IN_EXPECT: return NULL_TREE; + /* Prefetch instruction is not expensive. */ + case BUILT_IN_PREFETCH: + cost = 1; + break; default: break; } @@ -2155,15 +2191,15 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) if (!decl) { for (arg = TREE_OPERAND (x, 1); arg; arg = TREE_CHAIN (arg)) - *count += estimate_move_cost (TREE_TYPE (TREE_VALUE (arg))); + d->count += estimate_move_cost (TREE_TYPE (TREE_VALUE (arg))); } else { for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) - *count += estimate_move_cost (TREE_TYPE (arg)); + d->count += estimate_move_cost (TREE_TYPE (arg)); } - *count += PARAM_VALUE (PARAM_INLINE_CALL_COST); + d->count += cost; break; } @@ -2177,7 +2213,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) case OMP_CRITICAL: case OMP_ATOMIC: /* OpenMP directives are generally very expensive. */ - *count += 40; + d->count += d->weights->omp_cost; break; default: @@ -2186,16 +2222,20 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) return NULL; } -/* Estimate number of instructions that will be created by expanding EXPR. */ +/* Estimate number of instructions that will be created by expanding EXPR. + WEIGHTS contains weigths attributed to various constructs. */ int -estimate_num_insns (tree expr) +estimate_num_insns (tree expr, eni_weights *weights) { - int num = 0; struct pointer_set_t *visited_nodes; basic_block bb; block_stmt_iterator bsi; struct function *my_function; + struct eni_data data; + + data.count = 0; + data.weights = weights; /* If we're given an entire function, walk the CFG. */ if (TREE_CODE (expr) == FUNCTION_DECL) @@ -2210,15 +2250,40 @@ estimate_num_insns (tree expr) bsi_next (&bsi)) { walk_tree (bsi_stmt_ptr (bsi), estimate_num_insns_1, - &num, visited_nodes); + &data, visited_nodes); } } pointer_set_destroy (visited_nodes); } else - walk_tree_without_duplicates (&expr, estimate_num_insns_1, &num); + walk_tree_without_duplicates (&expr, estimate_num_insns_1, &data); - return num; + return data.count; +} + +/* Initializes weights used by estimate_num_insns. */ + +void +init_inline_once (void) +{ + eni_inlining_weights.call_cost = PARAM_VALUE (PARAM_INLINE_CALL_COST); + eni_inlining_weights.div_mod_cost = 10; + eni_inlining_weights.switch_cost = 1; + eni_inlining_weights.omp_cost = 40; + + eni_size_weights.call_cost = 1; + eni_size_weights.div_mod_cost = 1; + eni_size_weights.switch_cost = 10; + eni_size_weights.omp_cost = 40; + + /* Estimating time for call is difficult, since we have no idea what the + called function does. In the current uses of eni_time_weights, + underestimating the cost does less harm than overestimating it, so + we choose a rather small walue here. */ + eni_time_weights.call_cost = 10; + eni_time_weights.div_mod_cost = 10; + eni_time_weights.switch_cost = 4; + eni_time_weights.omp_cost = 40; } typedef struct function *function_p; |