Ping
2015-04-14 12:14 GMT+03:00 Ilya Enkovich <enkovich....@gmail.com>: > On 10 Apr 03:15, Jan Hubicka wrote: >> > >> > References are not streamed out for nodes which are referenced in a >> > partition but don't belong to it ('continue' condition in output_refs >> > loop). >> >> Yeah, but it already special cases aliases (because we now always preserve >> IPA_REF_ALIAS link >> in the boundary, so I think making IPA_REF_CHKP to be rpeserved should go >> the same path) >> so we can special case the instrumentation thunks too? > > Any cgraph_node having instrumented clone should have it, not only > instrumentation thunks. Surely we can make an exception for IPA_REF_CHKP. > >> > >> > > >> > > I suppose we still need to >> > > 1) write_symbol and lto-symtab should know that transparent aliases are >> > > not real >> > > symbols and ignore them. We have predicate >> > > symtab_node::real_symbol_p, >> > > I suppose it should return true. >> > > >> > > I think cgraph_merge and varpool_merge in lto-symtab needs to know >> > > what to do >> > > when merging two symbols with transparent aliases. >> > > 2) At some point we need to populate transparent alias links as >> > > discussed in the >> > > other thread. >> > > 3) For safety, I guess we want symbol_table::change_decl_assembler_name >> > > to either >> > > sanity check there are no trasparent alias links pointing to old >> > > assembler >> > > names or update it. >> > >> > Wouldn't search for possible referring via transparent aliases nodes >> > be too expensive? >> >> Changing of decl_assembler_name is not very common and if we set up the links >> only after renaming of statics, i think we are safe. But it would be better >> to >> keep verify it at some point. >> >> I suppose verify_node check that there is no transparent alias link on >> symbols >> were it is not supposed to be and that there is link when it is supposed to >> be (i.e. >> symtab_state is >=EXPANSION and symbol is either weakref on tragets w/o >> native weakrefs >> or instrumentation cone. >> >> Would you please mind adding the test and making sure it triggers when >> things are >> out of sync? >> > > OK, but I suppose it should be a part of transparent alias links rework > discussed in another thread. BTW are you going to intoroduce transparent > aliases in cgraph soon? > >> > >> > > 4) I think we want verify_node to check that transparent alias links >> > > and chkp points >> > > as intended and only on those symbols where they need to be >> > > >> > > There is also logic in lto-partition to always insert alias target >> > >> > OK, so you have the chkp references that links to >> > >> > instrumented_version. >> > >> > You do not stream them for boundary symbols but for some reason they >> > >> > are needed, >> > >> > but when you can end up with wrong CHKP link? >> > >> >> > >> Wrong links may appear when cgraph nodes are merged. >> > > >> > > I see, I think you really want to fix these at merging time as sugested >> > > in 1). >> > > In this case even the node->instrumented_version pointer may be out of >> > > date and >> > > point to a node that lost in merging? >> > >> > node->instrumented_version is redirected and never points to lost >> > symbol. But during merge we may have situations when >> > (node->instrumented_version->instrumented_version != node) because of >> > multiple not merged (yet) symbols referencing the same merged target. >> >> OK, which should not be a problem if we stream the links instead of >> rebuilding them, right? > > IPA_REF_CHKP refs don't affect instrumented_version merging. And I actually > don't see here any problems, instrumented_version links always come into > consistent state when symbol merging finishes. > > > Here is a new patch version. It has no chkp_maybe_fix_chkp_ref function, > IPA_REF_CHKP references are streamed out instead. Bootstrapped and tested on > x86_64-unknown-linux-gnu. OK for trunk? I also want to port it to GCC 5 > branch after release. > > Thanks, > Ilya > -- > gcc/ > > 2015-04-14 Ilya Enkovich <ilya.enkov...@intel.com> > > * ipa.c (symbol_table::remove_unreachable_nodes): Don't > remove instumentation thunks calling reachable functions. > * lto-cgraph.c (output_refs): Always output IPA_REF_CHKP. > * lto/lto-partition.c (privatize_symbol_name_1): New. > (privatize_symbol_name): Privatize both decl and orig_decl > names for instrumented functions. > > gcc/testsuite/ > > 2015-04-14 Ilya Enkovich <ilya.enkov...@intel.com> > > * gcc.dg/lto/chkp-privatize-1_0.c: New. > * gcc.dg/lto/chkp-privatize-1_1.c: New. > * gcc.dg/lto/chkp-privatize-2_0.c: New. > * gcc.dg/lto/chkp-privatize-2_1.c: New. > > > diff --git a/gcc/ipa.c b/gcc/ipa.c > index b3752de..3054afe 100644 > --- a/gcc/ipa.c > +++ b/gcc/ipa.c > @@ -492,7 +492,22 @@ symbol_table::remove_unreachable_nodes (FILE *file) > } > else if (cnode->thunk.thunk_p) > enqueue_node (cnode->callees->callee, &first, &reachable); > - > + > + /* For instrumentation clones we always need original > + function node for proper LTO privatization. */ > + if (cnode->instrumentation_clone > + && reachable.contains (cnode) > + && cnode->definition) > + { > + gcc_assert (cnode->instrumented_version || in_lto_p); > + if (cnode->instrumented_version) > + { > + enqueue_node (cnode->instrumented_version, &first, > + &reachable); > + reachable.add (cnode->instrumented_version); > + } > + } > + > /* If any reachable function has simd clones, mark them as > reachable as well. */ > if (cnode->simd_clones) > diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c > index ac50e4b..ea352f1 100644 > --- a/gcc/lto-cgraph.c > +++ b/gcc/lto-cgraph.c > @@ -805,8 +805,33 @@ output_refs (lto_symtab_encoder_t encoder) > { > symtab_node *node = lto_symtab_encoder_deref (encoder, i); > > + /* IPA_REF_ALIAS and IPA_REF_CHKP references are always preserved > + in the boundary. Alias node can't have other references and > + can be always handled as if it's not in the boundary. */ > if (!node->alias && !lto_symtab_encoder_in_partition_p (encoder, node)) > - continue; > + { > + cgraph_node *cnode = dyn_cast <cgraph_node *> (node); > + /* Output IPA_REF_CHKP reference. */ > + if (cnode > + && cnode->instrumented_version > + && !cnode->instrumentation_clone) > + { > + for (int i = 0; node->iterate_reference (i, ref); i++) > + if (ref->use == IPA_REF_CHKP) > + { > + if (lto_symtab_encoder_lookup (encoder, ref->referred) > + != LCC_NOT_FOUND) > + { > + int nref = lto_symtab_encoder_lookup (encoder, node); > + streamer_write_gcov_count_stream (ob->main_stream, 1); > + streamer_write_uhwi_stream (ob->main_stream, nref); > + lto_output_ref (ob, ref, encoder); > + } > + break; > + } > + } > + continue; > + } > > count = node->ref_list.nreferences (); > if (count) > diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c > index 235b735..7d117e9 100644 > --- a/gcc/lto/lto-partition.c > +++ b/gcc/lto/lto-partition.c > @@ -877,27 +877,13 @@ validize_symbol_for_target (symtab_node *node) > } > } > > -/* Mangle NODE symbol name into a local name. > - This is necessary to do > - 1) if two or more static vars of same assembler name > - are merged into single ltrans unit. > - 2) if previously static var was promoted hidden to avoid possible conflict > - with symbols defined out of the LTO world. */ > +/* Helper for privatize_symbol_name. Mangle NODE symbol name > + represented by DECL. */ > > static bool > -privatize_symbol_name (symtab_node *node) > +privatize_symbol_name_1 (symtab_node *node, tree decl) > { > - tree decl = node->decl; > - const char *name; > - cgraph_node *cnode = dyn_cast <cgraph_node *> (node); > - > - /* If we want to privatize instrumentation clone > - then we need to change original function name > - which is used via transparent alias chain. */ > - if (cnode && cnode->instrumentation_clone) > - decl = cnode->orig_decl; > - > - name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); > + const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); > > if (must_not_rename (node, name)) > return false; > @@ -906,31 +892,57 @@ privatize_symbol_name (symtab_node *node) > symtab->change_decl_assembler_name (decl, > clone_function_name_1 (name, > "lto_priv")); > + > if (node->lto_file_data) > lto_record_renamed_decl (node->lto_file_data, name, > IDENTIFIER_POINTER > (DECL_ASSEMBLER_NAME (decl))); > + > + if (symtab->dump_file) > + fprintf (symtab->dump_file, > + "Privatizing symbol name: %s -> %s\n", > + name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); > + > + return true; > +} > + > +/* Mangle NODE symbol name into a local name. > + This is necessary to do > + 1) if two or more static vars of same assembler name > + are merged into single ltrans unit. > + 2) if previously static var was promoted hidden to avoid possible conflict > + with symbols defined out of the LTO world. */ > + > +static bool > +privatize_symbol_name (symtab_node *node) > +{ > + if (!privatize_symbol_name_1 (node, node->decl)) > + return false; > + > /* We could change name which is a target of transparent alias > chain of instrumented function name. Fix alias chain if so .*/ > - if (cnode) > + if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) > { > tree iname = NULL_TREE; > if (cnode->instrumentation_clone) > - iname = DECL_ASSEMBLER_NAME (cnode->decl); > + { > + /* If we want to privatize instrumentation clone > + then we also need to privatize original function. */ > + if (cnode->instrumented_version) > + privatize_symbol_name (cnode->instrumented_version); > + else > + privatize_symbol_name_1 (cnode, cnode->orig_decl); > + iname = DECL_ASSEMBLER_NAME (cnode->decl); > + TREE_CHAIN (iname) = DECL_ASSEMBLER_NAME (cnode->orig_decl); > + } > else if (cnode->instrumented_version > - && cnode->instrumented_version->orig_decl == decl) > - iname = DECL_ASSEMBLER_NAME (cnode->instrumented_version->decl); > - > - if (iname) > + && cnode->instrumented_version->orig_decl == cnode->decl) > { > - gcc_assert (IDENTIFIER_TRANSPARENT_ALIAS (iname)); > - TREE_CHAIN (iname) = DECL_ASSEMBLER_NAME (decl); > + iname = DECL_ASSEMBLER_NAME (cnode->instrumented_version->decl); > + TREE_CHAIN (iname) = DECL_ASSEMBLER_NAME (cnode->decl); > } > } > - if (symtab->dump_file) > - fprintf (symtab->dump_file, > - "Privatizing symbol name: %s -> %s\n", > - name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); > + > return true; > } > > diff --git a/gcc/testsuite/gcc.dg/lto/chkp-privatize-1_0.c > b/gcc/testsuite/gcc.dg/lto/chkp-privatize-1_0.c > new file mode 100644 > index 0000000..2054aa15 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/lto/chkp-privatize-1_0.c > @@ -0,0 +1,17 @@ > +/* { dg-lto-do link } */ > +/* { dg-require-effective-target mpx } */ > +/* { dg-lto-options { { -Ofast -flto -fcheck-pointer-bounds -mmpx } } } */ > + > +extern int __attribute__((noinline)) f1 (int i); > + > +static int __attribute__((noinline)) > +f2 (int i) > +{ > + return i + 6; > +} > + > +int > +main (int argc, char **argv) > +{ > + return f1 (argc) + f2 (argc); > +} > diff --git a/gcc/testsuite/gcc.dg/lto/chkp-privatize-1_1.c > b/gcc/testsuite/gcc.dg/lto/chkp-privatize-1_1.c > new file mode 100644 > index 0000000..4fa8656 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/lto/chkp-privatize-1_1.c > @@ -0,0 +1,11 @@ > +static int __attribute__((noinline)) > +f2 (int i) > +{ > + return 2 * i; > +} > + > +int __attribute__((noinline)) > +f1 (int i) > +{ > + return f2 (i) + 10; > +} > diff --git a/gcc/testsuite/gcc.dg/lto/chkp-privatize-2_0.c > b/gcc/testsuite/gcc.dg/lto/chkp-privatize-2_0.c > new file mode 100644 > index 0000000..be7f601 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/lto/chkp-privatize-2_0.c > @@ -0,0 +1,18 @@ > +/* { dg-lto-do link } */ > +/* { dg-require-effective-target mpx } */ > +/* { dg-lto-options { { -Ofast -flto -fcheck-pointer-bounds -mmpx } } } */ > + > +static int > +__attribute__ ((noinline)) > +func1 (int i) > +{ > + return i + 2; > +} > + > +extern int func2 (int i); > + > +int > +main (int argc, char **argv) > +{ > + return func1 (argc) + func2 (argc) + 1; > +} > diff --git a/gcc/testsuite/gcc.dg/lto/chkp-privatize-2_1.c > b/gcc/testsuite/gcc.dg/lto/chkp-privatize-2_1.c > new file mode 100644 > index 0000000..db39e7f > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/lto/chkp-privatize-2_1.c > @@ -0,0 +1,8 @@ > +int func1 = 10; > + > +int > +func2 (int i) > +{ > + func1++; > + return i + func1; > +}