From 48de5d37c34a0d18b4f0e19e9ab3f661586ae9ee Mon Sep 17 00:00:00 2001 From: Ilya Enkovich Date: Wed, 3 Jun 2015 08:29:28 +0000 Subject: [PATCH] ipa.c (symbol_table::remove_unreachable_nodes): Don't remove instumentation thunks calling reachable functions. gcc/ * 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. * cgraph.c (cgraph_node::verify_node): Add transparent alias chain check for instrumented node. gcc/testsuite/ * 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. From-SVN: r224063 --- gcc/ChangeLog | 11 ++++ gcc/cgraph.c | 14 ++++++ gcc/ipa.c | 16 +++++- gcc/lto-cgraph.c | 27 +++++++++- gcc/lto/lto-partition.c | 72 ++++++++++++++++----------- gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.dg/lto/chkp-privatize-1_0.c | 17 +++++++ gcc/testsuite/gcc.dg/lto/chkp-privatize-1_1.c | 11 ++++ gcc/testsuite/gcc.dg/lto/chkp-privatize-2_0.c | 18 +++++++ gcc/testsuite/gcc.dg/lto/chkp-privatize-2_1.c | 8 +++ 10 files changed, 169 insertions(+), 32 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/lto/chkp-privatize-1_0.c create mode 100644 gcc/testsuite/gcc.dg/lto/chkp-privatize-1_1.c create mode 100644 gcc/testsuite/gcc.dg/lto/chkp-privatize-2_0.c create mode 100644 gcc/testsuite/gcc.dg/lto/chkp-privatize-2_1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ad33c67..baeaef5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2015-06-03 Ilya Enkovich + + * 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. + * cgraph.c (cgraph_node::verify_node): Add transparent + alias chain check for instrumented node. + 2015-06-03 Marek Polacek PR c/64223 diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 2ded5af..039ce15 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -3036,6 +3036,20 @@ cgraph_node::verify_node (void) } } + if (instrumentation_clone + && DECL_BUILT_IN_CLASS (decl) == NOT_BUILT_IN) + { + tree name = DECL_ASSEMBLER_NAME (decl); + tree orig_name = DECL_ASSEMBLER_NAME (orig_decl); + + if (!IDENTIFIER_TRANSPARENT_ALIAS (name) + || TREE_CHAIN (name) != orig_name) + { + error ("Alias chain for instrumented node is broken"); + error_found = true; + } + } + if (analyzed && thunk.thunk_p) { if (!callees) diff --git a/gcc/ipa.c b/gcc/ipa.c index eb6fd41..0b4010c 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -476,6 +476,20 @@ symbol_table::remove_unreachable_nodes (FILE *file) if (cnode->global.inlined_to) body_needed_for_clonning.add (cnode->decl); + /* For instrumentation clones we always need original + function node for proper LTO privatization. */ + if (cnode->instrumentation_clone + && 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); + } + } + /* For non-inline clones, force their origins to the boundary and ensure that body is not removed. */ while (cnode->clone_of) @@ -492,7 +506,7 @@ symbol_table::remove_unreachable_nodes (FILE *file) } else if (cnode->thunk.thunk_p) enqueue_node (cnode->callees->callee, &first, &reachable); - + /* 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 b306c28..b5fd83e 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -806,8 +806,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 (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 8c72d9e..e7c2214 100644 --- a/gcc/lto/lto-partition.c +++ b/gcc/lto/lto-partition.c @@ -900,27 +900,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 (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; @@ -929,31 +915,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 (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/ChangeLog b/gcc/testsuite/ChangeLog index d3280fc..12bf61c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-06-03 Ilya Enkovich + + * 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. + 2015-06-03 Marek Polacek PR c/64223 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; +} -- 2.7.4