https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63970
Bug ID: 63970 Summary: gcc-4_9 inlines less funcs than gcc-4_8 because of used_as_abstract_origin flag Product: gcc Version: 5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: wmi at google dot com CC: davidxl at google dot com, dehao at google dot com, hubicka at gcc dot gnu.org, rguenth at gcc dot gnu.org, tejohnson at google dot com We see an inline problem as below caused by r201408 (https://gcc.gnu.org/ml/gcc-patches/2013-08/msg00027.html). hoo() { foo(); ... } foo { goo(); ... } foo is func splitted, so its body changes to foo { goo(); ... foo.part(); } and the used_as_abstract_origin of cgraph node of foo will be set to true after func splitting. In ipa-inline, when inlining foo into hoo, the original node of foo will not be reused as clone node because used_as_abstract_origin of cgraph node of foo is true and can_remove_node_now_p_1 will return false, so that a new clone node of foo will be created. This is the case in gcc-4_9. In gcc-4_8, the original node of foo will be reused as clone node. gcc-4_8 foo | goo gcc-4_9 foo foo_clone \ / goo Because of the difference of whether to create a new clone for foo, when inlining goo to foo, the overall growth of inlining all callsites of goo in gcc-4_8 will be less than gcc-4_9 (goo has two callsites in gcc-4_9 but only one in gcc-4_8). If we have many cases like this, gcc-4_8 will actually have more inline growth budget than gcc-4_9 and will inline more aggressively than gcc-4_9. I don't understand the exact usage of the check about node->used_as_abstract_origin in can_remove_node_now_p_1, but I feel puzzled about following two points: 1. https://gcc.gnu.org/ml/gcc-patches/2013-08/msg00027.html said the patch was to ensure all abstract origin functions do have nodes attached. However, even if the node of origin function is reused as a clone node, a new clone node will be created in following code in symbol_table::remove_unreachable_nodes if only the node that needs abstract origin is reachable. if (TREE_CODE (node->decl) == FUNCTION_DECL && DECL_ABSTRACT_ORIGIN (node->decl)) { struct cgraph_node *origin_node = cgraph_node::get_create (DECL_ABSTRACT_ORIGIN (node->decl)); origin_node->used_as_abstract_origin = true; enqueue_node (origin_node, &first, &reachable); } 2. DECL_ABSTRACT_ORIGIN(decl) seems only useful for debug info of clone nodes. But now the check of used_as_abstract_origin affect inline decisions, which should be the same with or without keeping debug info.