Hi, while looking into Firefox's regressions WRT 4.9 LTO builds, I noticed that some of very small functions are not early inlined. This is because firefox sometimes uses always_inline and we skip early inlining int those. Once the always_inline is inlined we however do not inline recursively becuase we dropped number of iterations to 1.
This patch makes inliner to first apply changes of always inline prior early inlining. Bootstrapped/regtested x86_64-linux, will commit it shortly. * ipa-inline.c (early_inliner): Skip inlining only in always_inlined; if some always_inline was inlined, apply changes before inlining heuristically. Index: ipa-inline.c =================================================================== --- ipa-inline.c (revision 220313) +++ ipa-inline.c (working copy) @@ -2528,7 +2528,9 @@ early_inliner (function *fun) cycles of edges to be always inlined in the callgraph. We might want to be smarter and just avoid this type of inlining. */ - || DECL_DISREGARD_INLINE_LIMITS (node->decl)) + || (DECL_DISREGARD_INLINE_LIMITS (node->decl) + && lookup_attribute ("always_inline", + DECL_ATTRIBUTES (node->decl)))) ; else if (lookup_attribute ("flatten", DECL_ATTRIBUTES (node->decl)) != NULL) @@ -2543,6 +2545,17 @@ early_inliner (function *fun) } else { + /* If some always_inline functions was inlined, apply the changes. + This way we will not account always inline into growth limits and + moreover we will inline calls from always inlines that we skipped + previously becuase of conditional above. */ + if (inlined) + { + timevar_push (TV_INTEGRATION); + todo |= optimize_inline_calls (current_function_decl); + inline_update_overall_summary (node); + timevar_pop (TV_INTEGRATION); + } /* We iterate incremental inlining to get trivial cases of indirect inlining. */ while (iterations < PARAM_VALUE (PARAM_EARLY_INLINER_MAX_ITERATIONS)