https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68820
Jan Hubicka <hubicka at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Assignee|hubicka at gcc dot gnu.org |unassigned at gcc dot
gnu.org
--- Comment #10 from Jan Hubicka <hubicka at gcc dot gnu.org> ---
OK, this reproduces for me. We get:
Merging nodes for my_memcpy. Candidates:
my_memcpy/4 (my_memcpy) @0x7ffff6cc7450
Type: function definition analyzed
Visibility: force_output externally_visible public
next sharing asm name: 36
References:
Referring:
Read from file: memops-asm-lib.o
First run: 0
Function flags:
Called by:
Calls:
*my_memcpy/36 (memcpy) @0x7ffff6cc9a10
Type: function
Visibility: external public
next sharing asm name: 35
previous sharing asm name: 4
References:
Referring:
Read from file: memops-asm.o
First run: 0
Function flags:
Called by: main_test/31 (1.00 per call)
Calls:
*my_memcpy/35 (__builtin_memcpy) @0x7ffff6cc9b80
Type: function
Visibility: external public
previous sharing asm name: 36
References:
Referring:
Read from file: memops-asm.o
First run: 0
Function flags:
Called by: main_test/31 (1.00 per call)
Calls:
Not merging decls; DECL_BUILT_IN mismatch
Not merging decls; DECL_BUILT_IN mismatch
which is expected, one memcpy and __builtin_memcpy are builtins while my_memcpy
is not.
Now at ltrans time we have:
memcpy/8 (memcpy) @0x7ffff6ccb450
Type: function definition analyzed
Visibility: externally_visible public
References: inside_main/0 (read)
Referring:
Read from file: oo.ltrans0.o
First run: 0
Function flags:
Called by:
Calls: abort/13
i.e. unused memcpy and
my_memcpy/4 (my_memcpy) @0x7ffff6cc1e60
Type: function definition analyzed
Visibility: force_output externally_visible public
References:
Referring: *my_memcpy/36 (alias)
Read from file: oo.ltrans0.o
First run: 0
Function flags: nonfreeing_fn
Called by:
Calls:
*my_memcpy/36 (memcpy) @0x7ffff6cc1cf0
Type: function definition analyzed alias transparent_alias
Visibility: externally_visible external public
References: my_memcpy/4 (alias)
Referring:
Read from file: oo.ltrans0.o
First run: 0
Function flags:
Called by: main_test/31 (1.00 per call) main_test/31 (1.00 per call)
Calls:
i.e. used my_memcpy
Then we get to:
(gdb) bt
#0 expand_builtin_memcpy_args (dest=0x7ffff6923fe0, src=0x7ffff6923ca0,
len=0x7ffff6918b88, target=target@entry=0x7ffff69391e0,
exp=exp@entry=0x7ffff692eab0)
at ../../gcc/builtins.c:2904
#1 0x00000000005db286 in expand_builtin_memcpy (target=0x7ffff69391e0,
exp=0x7ffff692eab0) at ../../gcc/builtins.c:2991
#2 expand_builtin (exp=0x7ffff692eab0, target=0x7ffff69391e0, subtarget=0x0,
mode=DImode, ignore=0) at ../../gcc/builtins.c:5963
#3 0x00000000006c7bf4 in expand_expr_real_1 (exp=0x7ffff692eab0,
target=<optimized out>, tmode=DImode, modifier=EXPAND_NORMAL,
alt_rtl=<optimized out>,
inner_reference_p=inner_reference_p@entry=false) at ../../gcc/expr.c:10563
#4 0x00000000006c94a9 in expand_expr_real (exp=exp@entry=0x7ffff692eab0,
target=<optimized out>, tmode=<optimized out>,
modifier=modifier@entry=EXPAND_NORMAL,
alt_rtl=alt_rtl@entry=0x7fffffffe2b0,
inner_reference_p=inner_reference_p@entry=false) at ../../gcc/expr.c:7947
#5 0x00000000006d070a in store_expr_with_bounds (exp=exp@entry=0x7ffff692eab0,
target=target@entry=0x7ffff69391e0, call_param_p=call_param_p@entry=0,
nontemporal=nontemporal@entry=false, reverse=reverse@entry=false,
btarget=btarget@entry=0x7ffff6918bd0) at ../../gcc/expr.c:5406
#6 0x00000000006d1460 in expand_assignment (to=0x7ffff6918bd0,
from=from@entry=0x7ffff692eab0, nontemporal=nontemporal@entry=false) at
../../gcc/expr.c:5175
#7 0x00000000005f5904 in expand_call_stmt (stmt=0x7ffff6cbcbe0) at
../../gcc/cfgexpand.c:2646
#8 expand_gimple_stmt_1 (stmt=0x7ffff6cbcbe0) at ../../gcc/cfgexpand.c:3536
#9 expand_gimple_stmt (stmt=stmt@entry=0x7ffff6cbcbe0) at
../../gcc/cfgexpand.c:3702
#10 0x00000000005f71fd in expand_gimple_basic_block (bb=<optimized out>,
disable_tail_calls=disable_tail_calls@entry=false) at
../../gcc/cfgexpand.c:5708
#11 0x00000000005fc127 in (anonymous namespace)::pass_expand::execute
(this=<optimized out>, fun=0x7ffff6cd2930) at ../../gcc/cfgexpand.c:6323
#12 0x0000000000865bbe in execute_one_pass (pass=pass@entry=0x199b720) at
../../gcc/passes.c:2336
#13 0x0000000000866178 in execute_pass_list_1 (pass=0x199b720) at
../../gcc/passes.c:2410
#14 0x00000000008661d5 in execute_pass_list (fn=0x7ffff6cd2930, pass=<optimized
out>) at ../../gcc/passes.c:2421
#15 0x0000000000624943 in cgraph_node::expand (this=this@entry=0x7ffff6cc12e0)
at ../../gcc/cgraphunit.c:1973
#16 0x0000000000625f36 in expand_all_functions () at
../../gcc/cgraphunit.c:2109
#17 symbol_table::compile (this=0x7ffff6adb0a8) at ../../gcc/cgraphunit.c:2465
#18 0x0000000000626256 in symbol_table::compile (this=<optimized out>) at
../../gcc/cgraphunit.c:2498
#19 0x00000000005b7b01 in lto_main () at ../../gcc/lto/lto.c:3327
#20 0x000000000091413f in compile_file () at ../../gcc/toplev.c:464
#21 0x000000000058e101 in do_compile () at ../../gcc/toplev.c:1988
#22 toplev::main (this=this@entry=0x7fffffffe840, argc=<optimized out>,
argc@entry=30, argv=<optimized out>, argv@entry=0x7fffffffe948) at
../../gcc/toplev.c:2095
#23 0x00000000005902c7 in main (argc=30, argv=0x7fffffffe948) at
../../gcc/main.c:39
and the call target is still *my_memcpy and this goes to
emit_block_move_via_libcall which dispatches to memcpy because
init_block_move_fn decides so.
In normal compilation the user name of memcpy is set by:
#0 init_block_move_fn (asmspec=asmspec@entry=0x7ffff6bf0114 "my_memcpy") at
../../gcc/expr.c:1366
#1 0x0000000000665a6c in set_builtin_user_assembler_name
(decl=decl@entry=0x7ffff6b5cd20, asmspec=asmspec@entry=0x7ffff6bf0114
"my_memcpy") at ../../gcc/builtins.c:9697
#2 0x00000000005ae27b in finish_decl (decl=decl@entry=0x7ffff6b5cd20,
init_loc=init_loc@entry=0, init=<optimized out>, init@entry=0x0,
origtype=origtype@entry=0x0,
asmspec_tree=<optimized out>, asmspec_tree@entry=0x7ffff6bf0100) at
../../gcc/c/c-decl.c:4818
#3 0x00000000005db0be in c_parser_declaration_or_fndef
(parser=parser@entry=0x7ffff6c00000, fndef_ok=false, fndef_ok@entry=true,
static_assert_ok=static_assert_ok@entry=true,
empty_ok=empty_ok@entry=true, nested=nested@entry=false,
start_attr_ok=start_attr_ok@entry=true,
objc_foreach_object_declaration=<optimized out>, omp_declare_simd_clauses=...,
oacc_routine_clauses=<optimized out>) at ../../gcc/c/c-parser.c:1975
#4 0x00000000005f4c6e in c_parser_external_declaration (parser=0x7ffff6c00000)
at ../../gcc/c/c-parser.c:1532
#5 0x00000000005f568a in c_parser_translation_unit (parser=<optimized out>) at
../../gcc/c/c-parser.c:1419
#6 c_parse_file () at ../../gcc/c/c-parser.c:17802
#7 0x0000000000639963 in c_common_parse_file () at
../../gcc/c-family/c-opts.c:1064
#8 0x00000000009a419f in compile_file () at ../../gcc/toplev.c:464
#9 0x000000000059a9b1 in do_compile () at ../../gcc/toplev.c:1988
#10 toplev::main (this=this@entry=0x7fffffffe950, argc=<optimized out>,
argc@entry=19, argv=<optimized out>, argv@entry=0x7fffffffea58) at
../../gcc/toplev.c:2095
#11 0x000000000059cb47 in main (argc=19, argv=0x7fffffffea58) at
../../gcc/main.c:39
I think the testcase originally "worked" with LTO more or less by accident by
losing DECL_BUILTIN_IN flag during the merging. I do not see how this
machinery can work in LTO context: different translation units may have
different user name overrriders for memcpy and we do not preserve enough
context to known which one we want...
Perhaps we could just disable LTO for those tests?