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?

Reply via email to