diff options
Diffstat (limited to 'gold')
-rw-r--r-- | gold/ChangeLog | 26 | ||||
-rw-r--r-- | gold/gc.h | 2 | ||||
-rw-r--r-- | gold/gold.cc | 17 | ||||
-rw-r--r-- | gold/icf.cc | 24 | ||||
-rw-r--r-- | gold/main.cc | 2 | ||||
-rw-r--r-- | gold/object.cc | 8 | ||||
-rw-r--r-- | gold/options.cc | 9 | ||||
-rw-r--r-- | gold/options.h | 32 | ||||
-rw-r--r-- | gold/reloc.cc | 7 | ||||
-rw-r--r-- | gold/symtab.cc | 2 | ||||
-rw-r--r-- | gold/testsuite/Makefile.am | 14 | ||||
-rw-r--r-- | gold/testsuite/Makefile.in | 13 | ||||
-rw-r--r-- | gold/testsuite/icf_safe_test.cc | 54 | ||||
-rwxr-xr-x | gold/testsuite/icf_safe_test.sh | 50 |
14 files changed, 237 insertions, 23 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index c3c0dea..6c53383 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,29 @@ +2009-10-13 Sriraman Tallam <tmsriram@google.com> + + * gc.h (gc_process_relocs): Check if icf is enabled using new + function. + * gold.cc (queue_initial_tasks): Likewise. + (queue_middle_tasks): Likewise. + * object.cc (do_layout): Likewise. + * symtab.cc (is_section_folded): Likewise. + * main.cc (main): Likewise. + * reloc.cc (Read_relocs::run): Likewise. + (Sized_relobj::do_scan_relocs): Likewise. + * icf.cc (is_function_ctor_or_dtor): New function. + (Icf::find_identical_sections): Check if function is ctor or dtor when + safe icf is chosen. + * options.h (General_options::icf): Change option to be an enum. + (Icf_status): New enum. + (icf_enabled): New method. + (icf_safe_folding): New method. + (set_icf_status): New method. + (icf_status_): New variable. + * (options.cc) (General_options::finalize): Set icf_status_. + * testsuite/Makefile.am: Add commands to build icf_safe_test. Modify + icf_test and icf_keep_unique_test to use the --icf enum flag. + * testsuite/icf_safe_test.sh: New file. + * testsuite/icf_safe_test.cc: New file. + 2009-10-12 Sriraman Tallam <tmsriram@google.com> * symtab.h: Check for GOLD_SYMTAB_H before header includes. Remove @@ -163,7 +163,7 @@ gc_process_relocs( std::vector<std::pair<long long, long long> >* addendvec = NULL; bool is_icf_tracked = false; - if (parameters->options().icf() + if (parameters->options().icf_enabled() && is_prefix_of(".text.", (src_obj)->section_name(src_indx).c_str())) { is_icf_tracked = true; diff --git a/gold/gold.cc b/gold/gold.cc index 01a518f..909d7c3 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -221,10 +221,12 @@ queue_initial_tasks(const General_options& options, } if (parameters->options().relocatable() - && (parameters->options().gc_sections() || parameters->options().icf())) + && (parameters->options().gc_sections() + || parameters->options().icf_enabled())) gold_error(_("cannot mix -r with --gc-sections or --icf")); - if (parameters->options().gc_sections() || parameters->options().icf()) + if (parameters->options().gc_sections() + || parameters->options().icf_enabled()) { workqueue->queue(new Task_function(new Gc_runner(options, input_objects, @@ -332,7 +334,7 @@ queue_middle_tasks(const General_options& options, // If identical code folding (--icf) is chosen it makes sense to do it // only after garbage collection (--gc-sections) as we do not want to // be folding sections that will be garbage. - if (parameters->options().icf()) + if (parameters->options().icf_enabled()) { symtab->icf()->find_identical_sections(input_objects, symtab); } @@ -342,7 +344,8 @@ queue_middle_tasks(const General_options& options, // --gc-sections or --icf is turned on, Object::layout is // called twice. It is called the first time when the // symbols are added. - if (parameters->options().gc_sections() || parameters->options().icf()) + if (parameters->options().gc_sections() + || parameters->options().icf_enabled()) { for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); p != input_objects->relobj_end(); @@ -360,7 +363,8 @@ queue_middle_tasks(const General_options& options, plugins->layout_deferred_objects(); } - if (parameters->options().gc_sections() || parameters->options().icf()) + if (parameters->options().gc_sections() + || parameters->options().icf_enabled()) { for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); p != input_objects->relobj_end(); @@ -472,7 +476,8 @@ queue_middle_tasks(const General_options& options, // If doing garbage collection, the relocations have already been read. // Otherwise, read and scan the relocations. - if (parameters->options().gc_sections() || parameters->options().icf()) + if (parameters->options().gc_sections() + || parameters->options().icf_enabled()) { for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); p != input_objects->relobj_end(); diff --git a/gold/icf.cc b/gold/icf.cc index 411cf2e..03b927a 100644 --- a/gold/icf.cc +++ b/gold/icf.cc @@ -114,6 +114,7 @@ #include "icf.h" #include "symtab.h" #include "libiberty.h" +#include "demangle.h" namespace gold { @@ -530,6 +531,22 @@ match_sections(unsigned int iteration_num, return converged; } +// During safe icf (--icf=safe), only fold functions that are ctors or dtors. +// This function returns true if the mangled function name is a ctor or a +// dtor. + +static bool +is_function_ctor_or_dtor(const char* mangled_func_name) +{ + if ((is_prefix_of("_ZN", mangled_func_name) + || is_prefix_of("_ZZ", mangled_func_name)) + && (is_gnu_v3_mangled_ctor(mangled_func_name) + || is_gnu_v3_mangled_dtor(mangled_func_name))) + { + return true; + } + return false; +} // This is the main ICF function called in gold.cc. This does the // initialization and calls match_sections repeatedly (twice by default) @@ -552,14 +569,19 @@ Icf::find_identical_sections(const Input_objects* input_objects, { for (unsigned int i = 0;i < (*p)->shnum(); ++i) { + const char* section_name = (*p)->section_name(i).c_str(); // Only looking to fold functions, so just look at .text sections. - if (!is_prefix_of(".text.", (*p)->section_name(i).c_str())) + if (!is_prefix_of(".text.", section_name)) continue; if (!(*p)->is_section_included(i)) continue; if (parameters->options().gc_sections() && symtab->gc()->is_section_garbage(*p, i)) continue; + // With --icf=safe, check if mangled name is a ctor or a dtor. + if (parameters->options().icf_safe_folding() + && !is_function_ctor_or_dtor(section_name + 6)) + continue; this->id_section_.push_back(Section_id(*p, i)); this->section_id_[Section_id(*p, i)] = section_num; this->kept_section_id_.push_back(section_num); diff --git a/gold/main.cc b/gold/main.cc index d8ef582..66e8b24 100644 --- a/gold/main.cc +++ b/gold/main.cc @@ -220,7 +220,7 @@ main(int argc, char** argv) if (parameters->options().gc_sections()) symtab.set_gc(&gc); - if (parameters->options().icf()) + if (parameters->options().icf_enabled()) symtab.set_icf(&icf); // The layout object. diff --git a/gold/object.cc b/gold/object.cc index e09a71f..e9826b0 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -934,16 +934,16 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, const unsigned int shnum = this->shnum(); bool is_gc_pass_one = ((parameters->options().gc_sections() && !symtab->gc()->is_worklist_ready()) - || (parameters->options().icf() + || (parameters->options().icf_enabled() && !symtab->icf()->is_icf_ready())); bool is_gc_pass_two = ((parameters->options().gc_sections() && symtab->gc()->is_worklist_ready()) - || (parameters->options().icf() + || (parameters->options().icf_enabled() && symtab->icf()->is_icf_ready())); bool is_gc_or_icf = (parameters->options().gc_sections() - || parameters->options().icf()); + || parameters->options().icf_enabled()); // Both is_gc_pass_one and is_gc_pass_two should not be true. gold_assert(!(is_gc_pass_one && is_gc_pass_two)); @@ -1238,7 +1238,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, } } - if (is_gc_pass_two && parameters->options().icf()) + if (is_gc_pass_two && parameters->options().icf_enabled()) { if (out_sections[i] == NULL) { diff --git a/gold/options.cc b/gold/options.cc index 4e99653..5be414d 100644 --- a/gold/options.cc +++ b/gold/options.cc @@ -874,6 +874,15 @@ General_options::finalize() else if (this->noexecstack()) this->set_execstack_status(EXECSTACK_NO); + // icf_status_ is a three-state variable; update it based on the + // value of this->icf(). + if (strcmp(this->icf(), "none") == 0) + this->set_icf_status(ICF_NONE); + else if (strcmp(this->icf(), "safe") == 0) + this->set_icf_status(ICF_SAFE); + else + this->set_icf_status(ICF_ALL); + // Handle the optional argument for --demangle. if (this->user_set_demangle()) { diff --git a/gold/options.h b/gold/options.h index 848e648..f14582e 100644 --- a/gold/options.h +++ b/gold/options.h @@ -836,9 +836,11 @@ class General_options DEFINE_special(static, options::ONE_DASH, '\0', N_("Do not link against shared libraries"), NULL); - DEFINE_bool(icf, options::TWO_DASHES, '\0', false, - N_("Identical Code Folding (Fold identical functions)"), - N_("Don't fold identical functions (default)")); + DEFINE_enum(icf, options::TWO_DASHES, '\0', "none", + N_("Identical Code Folding. " + "\'--icf=safe\' folds only ctors and dtors."), + ("[none,all,safe]"), + {"none", "all", "safe"}); DEFINE_uint(icf_iterations, options::TWO_DASHES , '\0', 0, N_("Number of iterations of ICF (default 2)"), N_("COUNT")); @@ -1065,6 +1067,14 @@ class General_options is_stack_executable() const { return this->execstack_status_ == EXECSTACK_YES; } + bool + icf_enabled() const + { return this->icf_status_ != ICF_NONE; } + + bool + icf_safe_folding() const + { return this->icf_status_ == ICF_SAFE; } + // The --demangle option takes an optional string, and there is also // a --no-demangle option. This is the best way to decide whether // to demangle or not. @@ -1115,6 +1125,20 @@ class General_options EXECSTACK_NO }; + enum Icf_status + { + // Do not fold any functions (Default or --icf=none). + ICF_NONE, + // All functions are candidates for folding. (--icf=all). + ICF_ALL, + // Only ctors and dtors are candidates for folding. (--icf=safe). + ICF_SAFE + }; + + void + set_icf_status(Icf_status value) + { this->icf_status_ = value; } + void set_execstack_status(Execstack value) { this->execstack_status_ = value; } @@ -1148,6 +1172,8 @@ class General_options bool printed_version_; // Whether to mark the stack as executable. Execstack execstack_status_; + // Whether to do code folding. + Icf_status icf_status_; // Whether to do a static link. bool static_; // Whether to do demangling. diff --git a/gold/reloc.cc b/gold/reloc.cc index 7fb5cea..d618ea4 100644 --- a/gold/reloc.cc +++ b/gold/reloc.cc @@ -31,6 +31,7 @@ #include "object.h" #include "target-reloc.h" #include "reloc.h" +#include "icf.h" namespace gold { @@ -68,7 +69,8 @@ Read_relocs::run(Workqueue* workqueue) // If garbage collection or identical comdat folding is desired, we // process the relocs first before scanning them. Scanning of relocs is // done only after garbage or identical sections is identified. - if (parameters->options().gc_sections() || parameters->options().icf()) + if (parameters->options().gc_sections() + || parameters->options().icf_enabled()) { workqueue->queue_next(new Gc_process_relocs(this->options_, this->symtab_, @@ -420,7 +422,8 @@ Sized_relobj<size, big_endian>::do_scan_relocs(const General_options& options, // When garbage collection is on, unreferenced sections are not included // in the link that would have been included normally. This is known only // after Read_relocs hence this check has to be done again. - if (parameters->options().gc_sections() || parameters->options().icf()) + if (parameters->options().gc_sections() + || parameters->options().icf_enabled()) { if (p->output_section == NULL) continue; diff --git a/gold/symtab.cc b/gold/symtab.cc index 8a9e6f1..6d5038f 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -519,7 +519,7 @@ Symbol_table::Symbol_table_eq::operator()(const Symbol_table_key& k1, bool Symbol_table::is_section_folded(Object* obj, unsigned int shndx) const { - return (parameters->options().icf() + return (parameters->options().icf_enabled() && this->icf_->is_section_folded(obj, shndx)); } diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 7c03c9b..e5cb059 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -134,7 +134,7 @@ MOSTLYCLEANFILES += icf_test icf_test.o: icf_test.cc $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< icf_test: icf_test.o gcctestdir/ld - $(CXXLINK) -Bgcctestdir/ -Wl,--icf icf_test.o + $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all icf_test.o icf_test.stdout: icf_test $(TEST_NM) -C icf_test > icf_test.stdout @@ -144,10 +144,20 @@ MOSTLYCLEANFILES += icf_keep_unique_test icf_keep_unique_test.o: icf_keep_unique_test.cc $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< icf_keep_unique_test: icf_keep_unique_test.o gcctestdir/ld - $(CXXLINK) -Bgcctestdir/ -Wl,--icf -Wl,--keep-unique,_Z11unique_funcv icf_keep_unique_test.o + $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all -Wl,--keep-unique,_Z11unique_funcv icf_keep_unique_test.o icf_keep_unique_test.stdout: icf_keep_unique_test $(TEST_NM) -C icf_keep_unique_test > icf_keep_unique_test.stdout +check_SCRIPTS += icf_safe_test.sh +check_DATA += icf_safe_test.stdout +MOSTLYCLEANFILES += icf_safe_test +icf_safe_test.o: icf_safe_test.cc + $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +icf_safe_test: icf_safe_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,--icf=safe icf_safe_test.o +icf_safe_test.stdout: icf_safe_test + $(TEST_NM) icf_safe_test > icf_safe_test.stdout + check_PROGRAMS += basic_test check_PROGRAMS += basic_static_test check_PROGRAMS += basic_pic_test diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index b18784d..14c2cad 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -58,6 +58,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_1 = gc_comdat_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_tls_test.sh icf_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.sh weak_plt.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg.sh undef_symbol.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_1.sh ver_test_2.sh \ @@ -78,6 +79,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_tls_test.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_test.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.dbg \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_plt_shared.so debug_msg.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_so.err \ @@ -94,6 +96,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_3 = gc_comdat_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_tls_test icf_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.dbg \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/weak_undef_lib.so @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_4 = basic_test \ @@ -2606,15 +2609,21 @@ uninstall-am: @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_test.o: icf_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_test: icf_test.o gcctestdir/ld -@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf icf_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all icf_test.o @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_test.stdout: icf_test @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -C icf_test > icf_test.stdout @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_keep_unique_test.o: icf_keep_unique_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_keep_unique_test: icf_keep_unique_test.o gcctestdir/ld -@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf -Wl,--keep-unique,_Z11unique_funcv icf_keep_unique_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all -Wl,--keep-unique,_Z11unique_funcv icf_keep_unique_test.o @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_keep_unique_test.stdout: icf_keep_unique_test @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -C icf_keep_unique_test > icf_keep_unique_test.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_test.o: icf_safe_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_test: icf_safe_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=safe icf_safe_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_test.stdout: icf_safe_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) icf_safe_test > icf_safe_test.stdout @GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test.o: basic_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test: basic_test.o gcctestdir/ld diff --git a/gold/testsuite/icf_safe_test.cc b/gold/testsuite/icf_safe_test.cc new file mode 100644 index 0000000..9e8a369 --- /dev/null +++ b/gold/testsuite/icf_safe_test.cc @@ -0,0 +1,54 @@ +// icf_safe_test.cc -- a test case for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The goal of this program is to verify if identical code folding +// in safe mode correctly folds only ctors and dtors. kept_func_1 must +// not be folded into kept_func_2. The ctor and dtor of class A must +// be folded. + +class A +{ + public: + A() + { + } + ~A() + { + } +}; + +A a; + +int kept_func_1() +{ + return 1; +} + +int kept_func_2() +{ + return 1; +} + +int main() +{ + return 0; +} diff --git a/gold/testsuite/icf_safe_test.sh b/gold/testsuite/icf_safe_test.sh new file mode 100755 index 0000000..f77559c --- /dev/null +++ b/gold/testsuite/icf_safe_test.sh @@ -0,0 +1,50 @@ +# icf_safe_test.sh -- test --icf=safe + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Sriraman Tallam <tmsriram@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# The goal of this program is to verify if --icf=safe works as expected. +# File icf_safe_test.cc is in this test. This program checks if only +# ctors and dtors are folded. + +check_nofold() +{ + func_addr_1=`grep $2 $1 | awk '{print $1}'` + func_addr_2=`grep $3 $1 | awk '{print $1}'` + if [ $func_addr_1 = $func_addr_2 ] + then + echo "Safe Identical Code Folding folded" $2 "and" $3 + exit 1 + fi +} + +check_fold() +{ + func_addr_1=`grep $2 $1 | awk '{print $1}'` + func_addr_2=`grep $3 $1 | awk '{print $1}'` + if [ $func_addr_1 != $func_addr_2 ] + then + echo "Safe Identical Code Folding did not fold " $2 "and" $3 + exit 1 + fi +} + +check_nofold icf_safe_test.stdout "kept_func_1" "kept_func_2" +check_fold icf_safe_test.stdout "_ZN1AD1Ev" "_ZN1AC1Ev" |