aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-inline.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenth@tat.physik.uni-tuebingen.de>2005-03-22 20:53:40 +0000
committerJan Hubicka <jh@suse.cz>2005-03-22 20:53:40 +0000
commitaef99ee6c380d2d16c89316a75b9ecde3a08664f (patch)
treee6caff86555ce9f9639013c3cd82b4c469828776 /gcc/tree-inline.c
parent41ae5cb80ebc4b491cbc92589d6c1af726b3d4c2 (diff)
* cgraphunit.c (cgraph_estimate_size_after_inlining): Compute
call cost based on argument sizes. (cgraph_mark_inline_edge): Avoid inline unit from shringking by inlining. * params.def: (max-inline-inssn-single): Set to 450. (max-inline-insns-auto): Set to 90. (max-inline-insns-recursive): Set to 450 (max-inline-insns-recursive-auto): Set to 450. (large-function-insns): Set to 2700. (inline-call-cost): New parameter. * tree-inline.c (estimate_move_cost): New function. (estimate_num_insns_1): Compute move sizes costs by estimate_move_cost for non-gimple-regs, set cost to 0 for gimple-regs. Compute call size based on arguments. * tree-inline.h (estimate_move_cost): Declare. * invoke.texi: (max-inline-inssn-single): Change default to 450. (max-inline-insns-auto): Change default to 90. (max-inline-insns-recursive): Change default to 450 (max-inline-insns-recursive-auto): Change default to 450. (large-function-insns): Change default to 2700. (inline-call-cost): Document new parameter. * gcc.dg/winline-6.c: Modify so inlined function have nonzero cost. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@96892 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r--gcc/tree-inline.c79
1 files changed, 62 insertions, 17 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index c20c0744c70..6f46eed8c36 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1164,6 +1164,23 @@ inlinable_function_p (tree fn)
return inlinable;
}
+/* Estimate the cost of a memory move. Use machine dependent
+ word size and take possible memcpy call into account. */
+
+int
+estimate_move_cost (tree type)
+{
+ HOST_WIDE_INT size;
+
+ size = int_size_in_bytes (type);
+
+ if (size < 0 || size > MOVE_MAX_PIECES * MOVE_RATIO)
+ /* Cost of a memcpy call, 3 arguments and the call. */
+ return 4;
+ else
+ return ((size + MOVE_MAX_PIECES - 1) / MOVE_MAX_PIECES);
+}
+
/* Used by estimate_num_insns. Estimate number of instructions seen
by given statement. */
@@ -1242,28 +1259,50 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
*walk_subtrees = 0;
return NULL;
- /* Recognize assignments of large structures and constructors of
- big arrays. */
+ /* Try to estimate the cost of assignments. We have three cases to
+ deal with:
+ 1) Simple assignments to registers;
+ 2) Stores to things that must live in memory. This includes
+ "normal" stores to scalars, but also assignments of large
+ structures, or constructors of big arrays;
+ 3) TARGET_EXPRs.
+
+ Let us look at the first two cases, assuming we have "a = b + C":
+ <modify_expr <var_decl "a"> <plus_expr <var_decl "b"> <constant C>>
+ If "a" is a GIMPLE register, the assignment to it is free on almost
+ any target, because "a" usually ends up in a real register. Hence
+ the only cost of this expression comes from the PLUS_EXPR, and we
+ can ignore the MODIFY_EXPR.
+ If "a" is not a GIMPLE register, the assignment to "a" will most
+ likely be a real store, so the cost of the MODIFY_EXPR is the cost
+ of moving something into "a", which we compute using the function
+ estimate_move_cost.
+
+ The third case deals with TARGET_EXPRs, for which the semantics are
+ that a temporary is assigned, unless the TARGET_EXPR itself is being
+ assigned to something else. In the latter case we do not need the
+ temporary. E.g. in <modify_expr <var_decl "a"> <target_expr>>, the
+ MODIFY_EXPR is free. */
case INIT_EXPR:
case MODIFY_EXPR:
- x = TREE_OPERAND (x, 0);
- /* FALLTHRU */
+ /* Is the right and side a TARGET_EXPR? */
+ if (TREE_CODE (TREE_OPERAND (x, 1)) == TARGET_EXPR)
+ break;
+ /* ... fall through ... */
+
case TARGET_EXPR:
+ x = TREE_OPERAND (x, 0);
+ /* Is this an assignments to a register? */
+ if (is_gimple_reg (x))
+ break;
+ /* Otherwise it's a store, so fall through to compute the move cost. */
+
case CONSTRUCTOR:
- {
- HOST_WIDE_INT size;
-
- size = int_size_in_bytes (TREE_TYPE (x));
-
- if (size < 0 || size > MOVE_MAX_PIECES * MOVE_RATIO)
- *count += 10;
- else
- *count += ((size + MOVE_MAX_PIECES - 1) / MOVE_MAX_PIECES);
- }
+ *count += estimate_move_cost (TREE_TYPE (x));
break;
- /* Assign cost of 1 to usual operations.
- ??? We may consider mapping RTL costs to this. */
+ /* Assign cost of 1 to usual operations.
+ ??? We may consider mapping RTL costs to this. */
case COND_EXPR:
case PLUS_EXPR:
@@ -1350,6 +1389,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
case CALL_EXPR:
{
tree decl = get_callee_fndecl (x);
+ tree arg;
if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (decl))
@@ -1362,7 +1402,12 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
default:
break;
}
- *count += 10;
+
+ arg = TREE_OPERAND (x, 1);
+ for (arg = TREE_OPERAND (x, 1); arg; arg = TREE_CHAIN (arg))
+ *count += estimate_move_cost (TREE_TYPE (TREE_VALUE (arg)));
+
+ *count += PARAM_VALUE (PARAM_INLINE_CALL_COST);
break;
}
default: