On Wed, Jul 22, 2020 at 12:51 AM Gary Oblock via Gcc <gcc@gcc.gnu.org> wrote:
>
> Some background:
>
> This is in the dreaded structure reorganization optimization that I'm
> working on. It's running at LTRANS time with '-flto-partition=one'.
>
> My issues in order of importance are:
>
> 1) In gimple-ssa.h, the equal method for ssa_name_hasher
> has a segfault because the "var" field of "a" is (nil).
>
> struct ssa_name_hasher : ggc_ptr_hash<tree_node>
> {
>   /* Hash a tree in a uid_decl_map.  */
>
>   static hashval_t
>   hash (tree item)
>   {
>     return item->ssa_name.var->decl_minimal.uid;
>   }
>
>   /* Return true if the DECL_UID in both trees are equal.  */
>
>   static bool
>   equal (tree a, tree b)
>   {
>   return (a->ssa_name.var->decl_minimal.uid == 
> b->ssa_name.var->decl_minimal.uid);
>   }
> };
>
> The parameter "a" is associated with "*entry" on the 2nd to last
> line shown (it's trimmed off after that.) This from hash-table.h:
>
> template<typename Descriptor, bool Lazy,
> template<typename Type> class Allocator>
> typename hash_table<Descriptor, Lazy, Allocator>::value_type &
> hash_table<Descriptor, Lazy, Allocator>
> ::find_with_hash (const compare_type &comparable, hashval_t hash)
> {
>   m_searches++;
>   size_t size = m_size;
>   hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
>
>   if (Lazy && m_entries == NULL)
>     m_entries = alloc_entries (size);
>
> #if CHECKING_P
>   if (m_sanitize_eq_and_hash)
>     verify (comparable, hash);
> #endif
>
>   value_type *entry = &m_entries[index];
>   if (is_empty (*entry)
>       || (!is_deleted (*entry) && Descriptor::equal (*entry, comparable)))
>     return *entry;
>   .
>   .
>
> Is there any way this could happen other than by a memory corruption
> of some kind? This is a show stopper for me and I really need some help on
> this issue.
>
> 2) I tried to dump out all the gimple in the following way at the very
> beginning of my program:
>
> void
> print_program ( FILE *file, int leading_space )
> {
>   struct cgraph_node *node;
>   fprintf ( file, "%*sProgram:\n", leading_space, "");
>
>   // Print Global Decls
>   //
>   varpool_node *var;
>   FOR_EACH_VARIABLE ( var)
>   {
>     tree decl = var->decl;
>     fprintf ( file, "%*s", leading_space, "");
>     print_generic_decl ( file, decl, (dump_flags_t)0);
>     fprintf ( file, "\n");
>   }
>
>   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY ( node)
>   {
>     struct function *func = DECL_STRUCT_FUNCTION ( node->decl);
>     dump_function_header ( file, func->decl, (dump_flags_t)0);
>     dump_function_to_file ( func->decl, file, (dump_flags_t)0);
>   }
> }
>
> When I run this the first two (out of three) functions print
> just fine. However, for the third, func->decl is (nil) and
> it segfaults.
>
> Now the really odd thing is that this works perfectly at the
> end or middle of my optimization.
>
> What gives?
>
> 3) For my bug in (1) I got so distraught that I ran valgrind which
> in my experience is an act of desperation for compilers.
>
> None of the errors it spotted are associated with my optimization
> (although it oh so cleverly pointed out the segfault) however it
> showed the following:
>
> ==18572== Invalid read of size 8
> ==18572==    at 0x1079DC1: execute_one_pass(opt_pass*) (passes.c:2550)
> ==18572==    by 0x107ABD3: execute_ipa_pass_list(opt_pass*) (passes.c:2929)
> ==18572==    by 0xAC0E52: symbol_table::compile() (cgraphunit.c:2786)
> ==18572==    by 0x9915A9: lto_main() (lto.c:653)
> ==18572==    by 0x11EE4A0: compile_file() (toplev.c:458)
> ==18572==    by 0x11F1888: do_compile() (toplev.c:2302)
> ==18572==    by 0x11F1BA3: toplev::main(int, char**) (toplev.c:2441)
> ==18572==    by 0x23C021E: main (main.c:39)
> ==18572==  Address 0x5842880 is 16 bytes before a block of size 88 alloc'd
> ==18572==    at 0x4C3017F: operator new(unsigned long) (in 
> /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==18572==    by 0x21E00B7: make_pass_ipa_prototype(gcc::context*) 
> (ipa-prototype.c:329)
> ==18572==    by 0x106E987: gcc::pass_manager::pass_manager(gcc::context*) 
> (pass-instances.def:178)
> ==18572==    by 0x11EFCE8: general_init(char const*, bool) (toplev.c:1250)
> ==18572==    by 0x11F1A86: toplev::main(int, char**) (toplev.c:2391)
> ==18572==    by 0x23C021E: main (main.c:39)
> ==18572==
>
> Are these known issues with lto or is this a valgrind issue?

It smells like you are modifying IL via APIs that rely on cfun set to the
function you are modifying.  Note such API dependence might be not
obvious so it's advisable to do

 push_cfun (function to modify);
... modify IL of function ...
 pop_cfun ();

note push/pop_cfun can be expensive so try to glob function modifications.
That said, the underlying issue is likely garbage collector related - try
building with --enable-valgrind-annotations which makes valgrind a bit more
GCC GC aware.

Richard.

> Thanks,
>
> Gary
>
>
> CONFIDENTIALITY NOTICE: This e-mail message, including any attachments, is 
> for the sole use of the intended recipient(s) and contains information that 
> is confidential and proprietary to Ampere Computing or its subsidiaries. It 
> is to be used solely for the purpose of furthering the parties' business 
> relationship. Any review, copying, or distribution of this email (or any 
> attachments thereto) is strictly prohibited. If you are not the intended 
> recipient, please contact the sender immediately and permanently delete the 
> original and any copies of this email and any attachments thereto.

Reply via email to