On Thu, Jul 23, 2020 at 5:32 AM Gary Oblock <g...@amperecomputing.com> wrote:
>
> Richard,
>
> My wolf fence failed to detect an issue at the end of my pass
> so I'm now hunting for a problem I caused in a following pass.
>
> Your thoughts?

Sorry - I'd look at the IL after your pass for obvious mistakes.
All default defs need to have a VAR_DECL associated as
SSA_NAME_VAR.

> Gary
>
> ----- Wolf Fence Follows -----
> int
> wf_func ( tree *slot, tree *dummy)
> {
>   tree t_val = *slot;
>   gcc_assert( t_val->ssa_name.var);
>   return 0;
> }
>
> void
> wolf_fence (
>     Info *info // Pass level gobal info (might not use it)
>   )
> {
>   struct cgraph_node *node;
>   fprintf( stderr,
>   "Wolf Fence: Find wolf via gcc_assert(t_val->ssa_name.var)\n");
>   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY ( node)
>     {
>       struct function *func = DECL_STRUCT_FUNCTION ( node->decl);
>       push_cfun ( func);
>       DEFAULT_DEFS ( func)->traverse_noresize < tree *, wf_func> ( NULL);
>       pop_cfun ();
>     }
>   fprintf( stderr, "Wolf Fence: Didn't find wolf!\n");
> }
> ________________________________
> From: Richard Biener <richard.guent...@gmail.com>
> Sent: Wednesday, July 22, 2020 2:32 AM
> To: Gary Oblock <g...@amperecomputing.com>
> Cc: gcc@gcc.gnu.org <gcc@gcc.gnu.org>
> Subject: Re: Three issues
>
> [EXTERNAL EMAIL NOTICE: This email originated from an external sender. Please 
> be mindful of safe email handling and proprietary information protection 
> practices.]
>
>
> 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