https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79787
Alexander Ivchenko changed:
What|Removed |Added
CC||aivchenk at gmail dot com
--- Comment #2 from Alexander Ivchenko ---
Reduced testcase:
inline __attribute__((__always_inline__)) __attribute__ ((target("bmi"))) int
fn1() {}
__attribute__((__always_inline__)) __attribute__ ((target("bmi"))) int fn2() {
fn1(); }
int fn3() { return fn1(); }
Initial call graph:
fn3 -(not inlinable because of attribute mismatch)-> fn1
fn2 -> fn1
Call graph before chkp_ecleanup
fn3 -> fn3.chkp -(not inlinable because of attribute mismatch)-> fn1.chkp
fn2.chkp -> fn1.chkp
fn2 (fn1 is inlined here)
When compiler inlines fn1 to fn2 in expand_call_inline, it removes fn1 cnode,
as it is no longer needed.
There it execute this code (in cgraph_node::remove):
if (instrumented_version)
{
instrumented_version->instrumented_version = NULL;
instrumented_version = NULL;
}
Hence, now fn1.chkp.instrumened_version==NULL and fn1 is removed.
And later on in chkp_cleanup in reachability analysis in
symbol_table::remove_unreachable_nodes
we fail on this assert, where cnode==fn1.chkp
/* For instrumentation clones we always need original
function node for proper LTO privatization. */
if (cnode->instrumentation_clone
&& cnode->definition)
{
=>gcc_assert (cnode->instrumented_version || in_lto_p);
(since fn1 is removed, we don't consider it in chkp_produce_thunks
(early=false))