summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2011-04-30 14:08:03 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2011-04-30 14:08:03 +0000
commit6f60f0b6c6fb72967889f6a3e7a5ce20c325733b (patch)
treef8a79be03ab3f9bdbe5c053e8f6b97f09a0b90fe
parent06240b6f2eb94da0295bb1c121376b95b15c0ddd (diff)
downloadgcc-6f60f0b6c6fb72967889f6a3e7a5ce20c325733b.tar.gz
* ipa-inline.c (can_inline_edge_p): Disregard limits when
inlining into function with flatten attribute. (want_inline_small_function_p): Be more realistic about inlining cold calls where callee size grows. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@173216 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/ipa-inline.c44
2 files changed, 48 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fb69c09771c..2d7deb984e9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2011-04-30 Jan Hubicka <jh@suse.cz>
+ * ipa-inline.c (can_inline_edge_p): Disregard limits when
+ inlining into function with flatten attribute.
+ (want_inline_small_function_p): Be more realistic about inlining
+ cold calls where callee size grows.
+
+2011-04-30 Jan Hubicka <jh@suse.cz>
+
* cgraph.c (cgraph_create_virtual_clone): Clear constructor/destructor
flags.
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 1194785acaa..4665c82ac88 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -272,9 +272,11 @@ can_inline_edge_p (struct cgraph_edge *e, bool report)
FIXME: this is obviously wrong for LTO where STRUCT_FUNCTION is missing.
Move the flag into cgraph node or mirror it in the inline summary. */
else if (DECL_STRUCT_FUNCTION (e->callee->decl)
- && DECL_STRUCT_FUNCTION (e->callee->decl)->can_throw_non_call_exceptions
+ && DECL_STRUCT_FUNCTION
+ (e->callee->decl)->can_throw_non_call_exceptions
&& !(DECL_STRUCT_FUNCTION (e->caller->decl)
- && DECL_STRUCT_FUNCTION (e->caller->decl)->can_throw_non_call_exceptions))
+ && DECL_STRUCT_FUNCTION
+ (e->caller->decl)->can_throw_non_call_exceptions))
{
e->inline_failed = CIF_NON_CALL_EXCEPTIONS;
inlinable = false;
@@ -288,6 +290,11 @@ can_inline_edge_p (struct cgraph_edge *e, bool report)
}
/* Check if caller growth allows the inlining. */
else if (!DECL_DISREGARD_INLINE_LIMITS (e->callee->decl)
+ && !lookup_attribute ("flatten",
+ DECL_ATTRIBUTES
+ (e->caller->global.inlined_to
+ ? e->caller->global.inlined_to->decl
+ : e->caller->decl))
&& !caller_growth_limits (e))
inlinable = false;
/* Don't inline a function with a higher optimization level than the
@@ -468,8 +475,39 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
want_inline = false;
}
+ /* If call is cold, do not inline when function body would grow.
+ Still inline when the overall unit size will shrink because the offline
+ copy of function being eliminated.
+
+ This is slightly wrong on aggressive side: it is entirely possible
+ that function is called many times with a context where inlining
+ reduces code size and few times with a context where inlining increase
+ code size. Resoluting growth estimate will be negative even if it
+ would make more sense to keep offline copy and do not inline into the
+ call sites that makes the code size grow.
+
+ When badness orders the calls in a way that code reducing calls come
+ first, this situation is not a problem at all: after inlining all
+ "good" calls, we will realize that keeping the function around is
+ better. */
else if (!cgraph_maybe_hot_edge_p (e)
- && estimate_growth (e->callee) > 0)
+ && (DECL_EXTERNAL (e->callee->decl)
+
+ /* Unlike for functions called once, we play unsafe with
+ COMDATs. We can allow that since we know functions
+ in consideration are small (and thus risk is small) and
+ moreover grow estimates already accounts that COMDAT
+ functions may or may not disappear when eliminated from
+ current unit. With good probability making aggressive
+ choice in all units is going to make overall program
+ smaller.
+
+ Consequently we ask cgraph_can_remove_if_no_direct_calls_p
+ instead of
+ cgraph_will_be_removed_from_program_if_no_direct_calls */
+
+ || !cgraph_can_remove_if_no_direct_calls_p (e->callee)
+ || estimate_growth (e->callee) > 0))
{
e->inline_failed = CIF_UNLIKELY_CALL;
want_inline = false;