diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ad33c67fa12..baeaef58e02 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 2ded5af546e..039ce150fd8 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 eb6fd41a696..0b4010c3388 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 b306c28d37b..b5fd83ee7ab 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 8c72d9e9a41..e7c22140802 100644 --- a/gcc/lto/lto-partition.c +++ b/gcc/lto/lto-partition.c @@ -900,7 +900,36 @@ validize_symbol_for_target (symtab_node *node) } } -/* Mangle NODE symbol name into a local name. +/* Helper for privatize_symbol_name. Mangle NODE symbol name + represented by DECL. */ + +static bool +privatize_symbol_name_1 (symtab_node *node, tree decl) +{ + const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + + if (must_not_rename (node, name)) + return false; + + name = maybe_rewrite_identifier (name); + 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. @@ -910,50 +939,33 @@ validize_symbol_for_target (symtab_node *node) static bool privatize_symbol_name (symtab_node *node) { - 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)); - - if (must_not_rename (node, name)) + if (!privatize_symbol_name_1 (node, node->decl)) return false; - name = maybe_rewrite_identifier (name); - 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))); /* 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); - else if (cnode->instrumented_version - && cnode->instrumented_version->orig_decl == decl) - iname = DECL_ASSEMBLER_NAME (cnode->instrumented_version->decl); - - if (iname) { - gcc_assert (IDENTIFIER_TRANSPARENT_ALIAS (iname)); - TREE_CHAIN (iname) = DECL_ASSEMBLER_NAME (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 == cnode->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 d3280fc20f3..12bf61c614e 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 00000000000..2054aa15ba0 --- /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 00000000000..4fa8656d9a3 --- /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 00000000000..be7f601e399 --- /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 00000000000..db39e7fa9ef --- /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; +}