diff mbox

ipa-icf::merge TLC

Message ID 20150227021047.GA20437@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Feb. 27, 2015, 2:10 a.m. UTC
Hi,
this is the final version of patch I comitted.  It has new fix to make_decl_local
to set TREE_ADDRESSABLE becuase we leave the flag undefined for non-local decls.
I also dropped Optimization from fmerge-all-constants, fmerge-constants
those can not be done in function speicfic way, I made ipa_ref::address_matters_p
to use fmerge-constants, added code to drop UNINLINABLE flag when function is turned
into a wrapper, added check to require DECL_NO_INLINE_WARNING_P match
and added code to set TREE_ADDRESSABLE when non-addressable and addressable vars are merged.
I also disabled merging for DECL_CONSTANT_POOL because it does not work (symtab does not
expect aliases here)

Bootstrapped/regtested x86_64-linux, comitted.

Honza
	* ipa-icf.c (symbol_compare_collection::symbol_compare_colleciton):
	Use address_matters_p.
	(redirect_all_callers, set_addressable): New functions.
	(sem_function::merge): Reorganize and fix merging issues.
	(sem_variable::merge): Likewise.
	(sem_variable::compare_sections): Remove.
	* common.opt (fmerge-all-constants, fmerge-constants): Remove
	Optimization flag.
	* symtab.c (symtab_node::resolve_alias): When alias has aliases,
	redirect them.
	(symtab_node::make_decl_local): Set ADDRESSABLE bit when
	decl is used.
	(address_matters_1): New function.
	(symtab_node::address_matters_p): New function.
	* cgraph.c (cgraph_edge::verify_corresponds_to_fndecl): Fix
	check for merged flag.
	* cgraph.h (address_matters_p): Declare.
	(symtab_node::address_taken_from_non_vtable_p): Remove.
	(symtab_node::address_can_be_compared_p): New method.
	(ipa_ref::address_matters_p): Move here from ipa-ref.c; simplify.
	* ipa-visibility.c (symtab_node::address_taken_from_non_vtable_p):
	Remove.
	(comdat_can_be_unshared_p_1) Use address_matters_p.
	(update_vtable_references): Fix formating.
	* ipa-ref.c (ipa_ref::address_matters_p): Move inline.
	* cgraphunit.c (cgraph_node::create_wrapper): Drop UNINLINABLE flag.
	* cgraphclones.c: Preserve merged and icf_merged flags.

	* gcc.dg/pr64454.c: Disable ICF.
	* gcc.dg/pr28685-1.c: Disable ICF
	* gcc.dg/ipa/iinline-5.c: Disable ICF.
	* g++.dg/warn/Wsuggest-final.C: Force methods to be different.
	* g++.dg/ipa/ipa-icf-4.C: Update template.

Comments

H.J. Lu Feb. 27, 2015, 1:35 p.m. UTC | #1
On Thu, Feb 26, 2015 at 6:10 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
> Hi,
> this is the final version of patch I comitted.  It has new fix to make_decl_local
> to set TREE_ADDRESSABLE becuase we leave the flag undefined for non-local decls.
> I also dropped Optimization from fmerge-all-constants, fmerge-constants
> those can not be done in function speicfic way, I made ipa_ref::address_matters_p
> to use fmerge-constants, added code to drop UNINLINABLE flag when function is turned
> into a wrapper, added check to require DECL_NO_INLINE_WARNING_P match
> and added code to set TREE_ADDRESSABLE when non-addressable and addressable vars are merged.
> I also disabled merging for DECL_CONSTANT_POOL because it does not work (symtab does not
> expect aliases here)
>
> Bootstrapped/regtested x86_64-linux, comitted.
>
> Honza
>         * ipa-icf.c (symbol_compare_collection::symbol_compare_colleciton):
>         Use address_matters_p.
>         (redirect_all_callers, set_addressable): New functions.
>         (sem_function::merge): Reorganize and fix merging issues.
>         (sem_variable::merge): Likewise.
>         (sem_variable::compare_sections): Remove.
>         * common.opt (fmerge-all-constants, fmerge-constants): Remove
>         Optimization flag.
>         * symtab.c (symtab_node::resolve_alias): When alias has aliases,
>         redirect them.
>         (symtab_node::make_decl_local): Set ADDRESSABLE bit when
>         decl is used.
>         (address_matters_1): New function.
>         (symtab_node::address_matters_p): New function.
>         * cgraph.c (cgraph_edge::verify_corresponds_to_fndecl): Fix
>         check for merged flag.
>         * cgraph.h (address_matters_p): Declare.
>         (symtab_node::address_taken_from_non_vtable_p): Remove.
>         (symtab_node::address_can_be_compared_p): New method.
>         (ipa_ref::address_matters_p): Move here from ipa-ref.c; simplify.
>         * ipa-visibility.c (symtab_node::address_taken_from_non_vtable_p):
>         Remove.
>         (comdat_can_be_unshared_p_1) Use address_matters_p.
>         (update_vtable_references): Fix formating.
>         * ipa-ref.c (ipa_ref::address_matters_p): Move inline.
>         * cgraphunit.c (cgraph_node::create_wrapper): Drop UNINLINABLE flag.
>         * cgraphclones.c: Preserve merged and icf_merged flags.
>

This caused:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65237
Steve Ellcey Feb. 27, 2015, 5:33 p.m. UTC | #2
On Fri, 2015-02-27 at 03:10 +0100, Jan Hubicka wrote:

> Bootstrapped/regtested x86_64-linux, comitted.
> 
> Honza
> 	* ipa-icf.c (symbol_compare_collection::symbol_compare_colleciton):
> 	Use address_matters_p.

I think this patch is causing an ICE while building glibc on MIPS.  I am
building a toolchain for mips-mti-linux-gnu and when compiling
sysdeps/gnu/siglist.c from glibc for mips64r2 (N32 ABI) I get the
following ICE.

I will try to create a preprocessed source file for this but I wanted
to report it first to see if anyone else is seeing it on other
platforms.

Steve Ellcey
sellcey@imgtec.com



../sysdeps/gnu/siglist.c:72:1: internal compiler error: in address_matters_p, at symtab.c:1908
 versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev, GLIBC_2_3_3);
 ^
0x66a080 symtab_node::address_matters_p()
        /scratch/sellcey/repos/bootstrap/src/gcc/gcc/symtab.c:1908
0xe7cbe5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
        /scratch/sellcey/repos/bootstrap/src/gcc/gcc/ipa-icf.c:1443
0xe81ff9 ipa_icf::sem_item_optimizer::merge_classes(unsigned int)
        /scratch/sellcey/repos/bootstrap/src/gcc/gcc/ipa-icf.c:2659
0xe86491 ipa_icf::sem_item_optimizer::execute()
        /scratch/sellcey/repos/bootstrap/src/gcc/gcc/ipa-icf.c:1923
0xe885a1 ipa_icf_driver
        /scratch/sellcey/repos/bootstrap/src/gcc/gcc/ipa-icf.c:2738
0xe885a1 ipa_icf::pass_ipa_icf::execute(function*)
        /scratch/sellcey/repos/bootstrap/src/gcc/gcc/ipa-icf.c:2785
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.
make[2]: *** [/scratch/sellcey/repos/bootstrap/obj-mips-mti-linux-gnu/glibc/obj_mips64r2/stdio-common/siglist.os] Error 1
Steve Ellcey Feb. 27, 2015, 6:04 p.m. UTC | #3
On Fri, 2015-02-27 at 09:33 -0800, Steve Ellcey wrote:
> On Fri, 2015-02-27 at 03:10 +0100, Jan Hubicka wrote:
> 
> > Bootstrapped/regtested x86_64-linux, comitted.
> > 
> > Honza
> > 	* ipa-icf.c (symbol_compare_collection::symbol_compare_colleciton):
> > 	Use address_matters_p.
> 
> I think this patch is causing an ICE while building glibc on MIPS.  I am
> building a toolchain for mips-mti-linux-gnu and when compiling
> sysdeps/gnu/siglist.c from glibc for mips64r2 (N32 ABI) I get the
> following ICE.
> 
> I will try to create a preprocessed source file for this but I wanted
> to report it first to see if anyone else is seeing it on other
> platforms.
> 
> Steve Ellcey
> sellcey@imgtec.com

Following up to my own email.  I can reproduce this with the following
cut down test case if I compile with '-O2 -fmerge-all-constants' on
MIPS.

extern const char *const _sys_siglist[128];
const char *const __new_sys_siglist[128] = { };
extern __typeof (_sys_siglist) __EI__sys_siglist __attribute__((alias ("" "__new_sys_siglist")));
extern __typeof (__new_sys_siglist) _new_sys_siglist __attribute__ ((alias ("__new_sys_siglist")));

Steve Ellcey
sellcey@imgtec.com
Martin Liška Feb. 27, 2015, 6:56 p.m. UTC | #4
On 02/27/2015 07:04 PM, Steve Ellcey wrote:
> Following up to my own email.  I can reproduce this with the following
> cut down test case if I compile with '-O2 -fmerge-all-constants' on
> MIPS.
> 
> extern const char *const _sys_siglist[128];
> const char *const __new_sys_siglist[128] = { };
> extern __typeof (_sys_siglist) __EI__sys_siglist __attribute__((alias ("" "__new_sys_siglist")));
> extern __typeof (__new_sys_siglist) _new_sys_siglist __attribute__ ((alias ("__new_sys_siglist")));
> 
> Steve Ellcey
> sellcey@imgtec.com

Hello.

I've just created PR65245, where I've attached suggested patch I'm testing.

Thanks,
Martin
Jan Hubicka Feb. 27, 2015, 8:49 p.m. UTC | #5
> 
> ../sysdeps/gnu/siglist.c:72:1: internal compiler error: in address_matters_p, at symtab.c:1908
>  versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev, GLIBC_2_3_3);
>  ^
> 0x66a080 symtab_node::address_matters_p()
>         /scratch/sellcey/repos/bootstrap/src/gcc/gcc/symtab.c:1908
> 0xe7cbe5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
>         /scratch/sellcey/repos/bootstrap/src/gcc/gcc/ipa-icf.c:1443

Indeed, the ipa-icf should not try to analyze aliases - just prove ekvialence of
definitions they are attached to.  It already does that for functions (bit by accident;
it gives up when there is no gimple body), but it does not do that for variables because
it gets into ctor_for_folding. For that reason it sometimes decides to try to make two
variable aliases alias of each other that is not a good idea, because of possible creation
of loops.

I am just discussing with Martin the fix.

Honza
James Greenhalgh Feb. 28, 2015, 10:13 a.m. UTC | #6
On Fri, Feb 27, 2015 at 02:10:47AM +0000, Jan Hubicka wrote:
>         * ipa-icf.c (symbol_compare_collection::symbol_compare_colleciton):
>         Use address_matters_p.
>         (redirect_all_callers, set_addressable): New functions.
>         (sem_function::merge): Reorganize and fix merging issues.
>         (sem_variable::merge): Likewise.
>         (sem_variable::compare_sections): Remove.
>         * common.opt (fmerge-all-constants, fmerge-constants): Remove
>         Optimization flag.
>         * symtab.c (symtab_node::resolve_alias): When alias has aliases,
>         redirect them.
>         (symtab_node::make_decl_local): Set ADDRESSABLE bit when
>         decl is used.
>         (address_matters_1): New function.
>         (symtab_node::address_matters_p): New function.
>         * cgraph.c (cgraph_edge::verify_corresponds_to_fndecl): Fix
>         check for merged flag.
>         * cgraph.h (address_matters_p): Declare.
>         (symtab_node::address_taken_from_non_vtable_p): Remove.
>         (symtab_node::address_can_be_compared_p): New method.
>         (ipa_ref::address_matters_p): Move here from ipa-ref.c; simplify.
>         * ipa-visibility.c (symtab_node::address_taken_from_non_vtable_p):
>         Remove.
>         (comdat_can_be_unshared_p_1) Use address_matters_p.
>         (update_vtable_references): Fix formating.
>         * ipa-ref.c (ipa_ref::address_matters_p): Move inline.
>         * cgraphunit.c (cgraph_node::create_wrapper): Drop UNINLINABLE flag.
>         * cgraphclones.c: Preserve merged and icf_merged flags.
> 
>         * gcc.dg/pr64454.c: Disable ICF.
>         * gcc.dg/pr28685-1.c: Disable ICF
>         * gcc.dg/ipa/iinline-5.c: Disable ICF.
>         * g++.dg/warn/Wsuggest-final.C: Force methods to be different.
>         * g++.dg/ipa/ipa-icf-4.C: Update template.

Hi Honza,

This is more a note for other interested AArch64 testers, but this patch
breaks some tests on aarch64-none-elf. Looking at the test output, this
is a problem with the tests than with your patch. We now eliminate some
function bodies which are identical across test functions, causing us to
fail some scan-assembler directives.

The fix is straightforward, we just need to add -fno-ipa-icf to get things
working again. This keeps the spirit of the original tests. I'll propose
a patch along those lines on Monday.

Thanks,
James

---

        PASS->FAIL: gcc.target/aarch64/atomic-comp-swap-release-acquire.c scan-assembler-times ldaxr\tw[0-9]+, \\[x[0-9]+\\] 4
        PASS->FAIL: gcc.target/aarch64/atomic-comp-swap-release-acquire.c scan-assembler-times stlxr\tw[0-9]+, w[0-9]+, \\[x[0-9]+\\] 4
        PASS->FAIL: gcc.target/aarch64/vect_saddl_1.c scan-assembler-times saddl2\tv[0-9]+.2d, v[0-9]+.4s, v[0-9]+.4s 2
        PASS->FAIL: gcc.target/aarch64/vect_saddl_1.c scan-assembler-times saddl\tv[0-9]+.2d, v[0-9]+.2s, v[0-9]+.2s 2
        PASS->FAIL: gcc.target/aarch64/vect_saddl_1.c scan-assembler-times ssubl2\tv[0-9]+.2d, v[0-9]+.4s, v[0-9]+.4s 5
        PASS->FAIL: gcc.target/aarch64/vect_saddl_1.c scan-assembler-times ssubl\tv[0-9]+.2d, v[0-9]+.2s, v[0-9]+.2s 5
        PASS->FAIL: gcc.target/aarch64/vect_smlal_1.c scan-assembler-times smlsl2\tv[0-9]+.8h 5
        PASS->FAIL: gcc.target/aarch64/vect_smlal_1.c scan-assembler-times smlsl\tv[0-9]+.8h 5
Jan Hubicka Feb. 28, 2015, 6:08 p.m. UTC | #7
> 
> Hi Honza,
> 
> This is more a note for other interested AArch64 testers, but this patch
> breaks some tests on aarch64-none-elf. Looking at the test output, this
> is a problem with the tests than with your patch. We now eliminate some
> function bodies which are identical across test functions, causing us to
> fail some scan-assembler directives.
> 
> The fix is straightforward, we just need to add -fno-ipa-icf to get things
> working again. This keeps the spirit of the original tests. I'll propose
> a patch along those lines on Monday.
> 
> Thanks,
> James
> 
> ---
> 
>         PASS->FAIL: gcc.target/aarch64/atomic-comp-swap-release-acquire.c scan-assembler-times ldaxr\tw[0-9]+, \\[x[0-9]+\\] 4
>         PASS->FAIL: gcc.target/aarch64/atomic-comp-swap-release-acquire.c scan-assembler-times stlxr\tw[0-9]+, w[0-9]+, \\[x[0-9]+\\] 4
>         PASS->FAIL: gcc.target/aarch64/vect_saddl_1.c scan-assembler-times saddl2\tv[0-9]+.2d, v[0-9]+.4s, v[0-9]+.4s 2
>         PASS->FAIL: gcc.target/aarch64/vect_saddl_1.c scan-assembler-times saddl\tv[0-9]+.2d, v[0-9]+.2s, v[0-9]+.2s 2
>         PASS->FAIL: gcc.target/aarch64/vect_saddl_1.c scan-assembler-times ssubl2\tv[0-9]+.2d, v[0-9]+.4s, v[0-9]+.4s 5
>         PASS->FAIL: gcc.target/aarch64/vect_saddl_1.c scan-assembler-times ssubl\tv[0-9]+.2d, v[0-9]+.2s, v[0-9]+.2s 5
>         PASS->FAIL: gcc.target/aarch64/vect_smlal_1.c scan-assembler-times smlsl2\tv[0-9]+.8h 5
>         PASS->FAIL: gcc.target/aarch64/vect_smlal_1.c scan-assembler-times smlsl\tv[0-9]+.8h 5

Thanks, yes adding -fno-ipa-icf is a proper fix for tests like this.
What happened was a logic bug in old implementation of merge routine.  When
symbol is externally visible it decided to create a wrapper (to preserve
potential address compares) and to avoid wrapper cost redirect all direct
uses.

There was extra else between redirection and thunk creation, so often it
redirected calls but it kept old function body in code.  We now see a lot more
DCE tham before.

i386 tests also needed a compensation at two places.

Honza
Christophe Lyon March 1, 2015, 4:47 p.m. UTC | #8
On 27 February 2015 at 21:49, Jan Hubicka <hubicka@ucw.cz> wrote:
>>
>> ../sysdeps/gnu/siglist.c:72:1: internal compiler error: in address_matters_p, at symtab.c:1908
>>  versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev, GLIBC_2_3_3);
>>  ^
>> 0x66a080 symtab_node::address_matters_p()
>>         /scratch/sellcey/repos/bootstrap/src/gcc/gcc/symtab.c:1908
>> 0xe7cbe5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
>>         /scratch/sellcey/repos/bootstrap/src/gcc/gcc/ipa-icf.c:1443
>
> Indeed, the ipa-icf should not try to analyze aliases - just prove ekvialence of
> definitions they are attached to.  It already does that for functions (bit by accident;
> it gives up when there is no gimple body), but it does not do that for variables because
> it gets into ctor_for_folding. For that reason it sometimes decides to try to make two
> variable aliases alias of each other that is not a good idea, because of possible creation
> of loops.
>
> I am just discussing with Martin the fix.
>
> Honza

For the record, I have noticed similar errors on ARM and AArch64
targets, when building glibc.

Christophe.
Alex Velenko March 2, 2015, 7 p.m. UTC | #9
On 01/03/15 16:47, Christophe Lyon wrote:
> On 27 February 2015 at 21:49, Jan Hubicka <hubicka@ucw.cz> wrote:
>>>
>>> ../sysdeps/gnu/siglist.c:72:1: internal compiler error: in address_matters_p, at symtab.c:1908
>>>   versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev, GLIBC_2_3_3);
>>>   ^
>>> 0x66a080 symtab_node::address_matters_p()
>>>          /scratch/sellcey/repos/bootstrap/src/gcc/gcc/symtab.c:1908
>>> 0xe7cbe5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
>>>          /scratch/sellcey/repos/bootstrap/src/gcc/gcc/ipa-icf.c:1443
>>
>> Indeed, the ipa-icf should not try to analyze aliases - just prove ekvialence of
>> definitions they are attached to.  It already does that for functions (bit by accident;
>> it gives up when there is no gimple body), but it does not do that for variables because
>> it gets into ctor_for_folding. For that reason it sometimes decides to try to make two
>> variable aliases alias of each other that is not a good idea, because of possible creation
>> of loops.
>>
>> I am just discussing with Martin the fix.
>>
>> Honza
>
> For the record, I have noticed similar errors on ARM and AArch64
> targets, when building glibc.
>
> Christophe.
>

I confirm ARM and AArch64 failing to build with this patch:

/work/build-aarch64-none-linux-gnu/install//bin/aarch64-none-linux-gnu-gcc 
../sysdeps/posix/cuserid.c -c -std=gnu99 -fgnu89-inline  -O2 -Wall 
-Winline -Wundef -Wwrite-strings -fmerge-all-constants -frounding-math 
-g -Wstrict-prototypes   -fPIC -fexceptions       -I../include 
-I/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common 
-I/work/build-aarch64-none-linux-gnu/obj/glibc 
-I../sysdeps/unix/sysv/linux/aarch64  -I../sysdeps/aarch64/nptl 
-I../sysdeps/unix/sysv/linux/generic 
-I../sysdeps/unix/sysv/linux/wordsize-64 
-I../sysdeps/unix/sysv/linux/include -I../sysdeps/unix/sysv/linux 
-I../sysdeps/nptl  -I../sysdeps/pthread  -I../sysdeps/gnu 
-I../sysdeps/unix/inet  -I../sysdeps/unix/sysv  -I../sysdeps/unix 
-I../sysdeps/posix  -I../sysdeps/aarch64/fpu  -I../sysdeps/aarch64 
-I../sysdeps/wordsize-64  -I../sysdeps/ieee754/ldbl-128 
-I../sysdeps/ieee754/dbl-64/wordsize-64  -I../sysdeps/ieee754/dbl-64 
-I../sysdeps/ieee754/flt-32  -I../sysdeps/aarch64/soft-fp 
-I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I. 
-nostdinc -isystem 
/work/build-aarch64-none-linux-gnu/install/bin/../lib/gcc/aarch64-none-linux-gnu/5.0.0/include 
-isystem 
/work/build-aarch64-none-linux-gnu/install/bin/../lib/gcc/aarch64-none-linux-gnu/5.0.0/include-fixed 
-isystem 
/work/build-aarch64-none-linux-gnu/install//aarch64-none-linux-gnu/libc/usr/include 
  -D_LIBC_REENTRANT -include 
/work/build-aarch64-none-linux-gnu/obj/glibc/libc-modules.h 
-DMODULE_NAME=libc -include ../include/libc-symbols.h  -DPIC -DSHARED 
   -D_IO_MTSAFE_IO -o 
/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/cuserid.os -MD 
-MP -MF 
/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/cuserid.os.dt 
-MT /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/cuserid.os
../sysdeps/gnu/siglist.c:77:1: internal compiler error: in 
address_matters_p, at symtab.c:1908
  versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev, GLIBC_2_1);
  ^
*** errlist.c count 134 inflated to GLIBC_2.12 count 135 (old errno.h?)
chmod a-w 
/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.cT
0x6b9100 symtab_node::address_matters_p()
	/work/src/gcc/gcc/symtab.c:1908
0xedb4e5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
	/work/src/gcc/gcc/ipa-icf.c:1723
0xee03f9 ipa_icf::sem_item_optimizer::merge_classes(unsigned int)
	/work/src/gcc/gcc/ipa-icf.c:2955
0xee6d31 ipa_icf::sem_item_optimizer::execute()
	/work/src/gcc/gcc/ipa-icf.c:2217
0xee8df1 ipa_icf_driver
	/work/src/gcc/gcc/ipa-icf.c:3034
0xee8df1 ipa_icf::pass_ipa_icf::execute(function*)
	/work/src/gcc/gcc/ipa-icf.c:3081
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.
make[2]: *** 
[/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/siglist.o] 
Error 1
make[2]: *** Waiting for unfinished jobs....
mv -f 
/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.cT 
/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.c

Regards,
Alex
Jan Hubicka March 2, 2015, 8:21 p.m. UTC | #10
> 
> 
> On 01/03/15 16:47, Christophe Lyon wrote:
> >On 27 February 2015 at 21:49, Jan Hubicka <hubicka@ucw.cz> wrote:
> >>>
> >>>../sysdeps/gnu/siglist.c:72:1: internal compiler error: in address_matters_p, at symtab.c:1908
> >>>  versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev, GLIBC_2_3_3);
> >>>  ^
> >>>0x66a080 symtab_node::address_matters_p()
> >>>         /scratch/sellcey/repos/bootstrap/src/gcc/gcc/symtab.c:1908
> >>>0xe7cbe5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
> >>>         /scratch/sellcey/repos/bootstrap/src/gcc/gcc/ipa-icf.c:1443
> >>
> >>Indeed, the ipa-icf should not try to analyze aliases - just prove ekvialence of
> >>definitions they are attached to.  It already does that for functions (bit by accident;
> >>it gives up when there is no gimple body), but it does not do that for variables because
> >>it gets into ctor_for_folding. For that reason it sometimes decides to try to make two
> >>variable aliases alias of each other that is not a good idea, because of possible creation
> >>of loops.
> >>
> >>I am just discussing with Martin the fix.
> >>
> >>Honza
> >
> >For the record, I have noticed similar errors on ARM and AArch64
> >targets, when building glibc.
> >
> >Christophe.
> >
> 
> I confirm ARM and AArch64 failing to build with this patch:
> chmod a-w /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.cT
> 0x6b9100 symtab_node::address_matters_p()
> 	/work/src/gcc/gcc/symtab.c:1908
> 0xedb4e5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
> 	/work/src/gcc/gcc/ipa-icf.c:1723
> 0xee03f9 ipa_icf::sem_item_optimizer::merge_classes(unsigned int)
> 	/work/src/gcc/gcc/ipa-icf.c:2955
> 0xee6d31 ipa_icf::sem_item_optimizer::execute()
> 	/work/src/gcc/gcc/ipa-icf.c:2217
> 0xee8df1 ipa_icf_driver
> 	/work/src/gcc/gcc/ipa-icf.c:3034
> 0xee8df1 ipa_icf::pass_ipa_icf::execute(function*)
> 	/work/src/gcc/gcc/ipa-icf.c:3081

I commited patch for the alias merging yesterda night, so it should be fixed
now.  If it still fails, please fill in a PR with preprocessed testcase so I
can reproduce it in a cross.

Honza
> Please submit a full bug report,
> with preprocessed source if appropriate.
> Please include the complete backtrace with any bug report.
> See <http://gcc.gnu.org/bugs.html> for instructions.
> make[2]: ***
> [/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/siglist.o]
> Error 1
> make[2]: *** Waiting for unfinished jobs....
> mv -f /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.cT /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.c
> 
> Regards,
> Alex
Christophe Lyon March 2, 2015, 10:04 p.m. UTC | #11
On 2 March 2015 at 21:21, Jan Hubicka <hubicka@ucw.cz> wrote:
>>
>>
>> On 01/03/15 16:47, Christophe Lyon wrote:
>> >On 27 February 2015 at 21:49, Jan Hubicka <hubicka@ucw.cz> wrote:
>> >>>
>> >>>../sysdeps/gnu/siglist.c:72:1: internal compiler error: in address_matters_p, at symtab.c:1908
>> >>>  versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev, GLIBC_2_3_3);
>> >>>  ^
>> >>>0x66a080 symtab_node::address_matters_p()
>> >>>         /scratch/sellcey/repos/bootstrap/src/gcc/gcc/symtab.c:1908
>> >>>0xe7cbe5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
>> >>>         /scratch/sellcey/repos/bootstrap/src/gcc/gcc/ipa-icf.c:1443
>> >>
>> >>Indeed, the ipa-icf should not try to analyze aliases - just prove ekvialence of
>> >>definitions they are attached to.  It already does that for functions (bit by accident;
>> >>it gives up when there is no gimple body), but it does not do that for variables because
>> >>it gets into ctor_for_folding. For that reason it sometimes decides to try to make two
>> >>variable aliases alias of each other that is not a good idea, because of possible creation
>> >>of loops.
>> >>
>> >>I am just discussing with Martin the fix.
>> >>
>> >>Honza
>> >
>> >For the record, I have noticed similar errors on ARM and AArch64
>> >targets, when building glibc.
>> >
>> >Christophe.
>> >
>>
>> I confirm ARM and AArch64 failing to build with this patch:
>> chmod a-w /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.cT
>> 0x6b9100 symtab_node::address_matters_p()
>>       /work/src/gcc/gcc/symtab.c:1908
>> 0xedb4e5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
>>       /work/src/gcc/gcc/ipa-icf.c:1723
>> 0xee03f9 ipa_icf::sem_item_optimizer::merge_classes(unsigned int)
>>       /work/src/gcc/gcc/ipa-icf.c:2955
>> 0xee6d31 ipa_icf::sem_item_optimizer::execute()
>>       /work/src/gcc/gcc/ipa-icf.c:2217
>> 0xee8df1 ipa_icf_driver
>>       /work/src/gcc/gcc/ipa-icf.c:3034
>> 0xee8df1 ipa_icf::pass_ipa_icf::execute(function*)
>>       /work/src/gcc/gcc/ipa-icf.c:3081
>
> I commited patch for the alias merging yesterda night, so it should be fixed
> now.  If it still fails, please fill in a PR with preprocessed testcase so I
> can reproduce it in a cross.
>

On my side, I saw builds complete again starting with r221090, I guess
that's the commit you are referring to?

Thanks,

Christophe.

> Honza
>> Please submit a full bug report,
>> with preprocessed source if appropriate.
>> Please include the complete backtrace with any bug report.
>> See <http://gcc.gnu.org/bugs.html> for instructions.
>> make[2]: ***
>> [/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/siglist.o]
>> Error 1
>> make[2]: *** Waiting for unfinished jobs....
>> mv -f /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.cT /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.c
>>
>> Regards,
>> Alex
Alex Velenko March 3, 2015, 12:44 p.m. UTC | #12
On 02/03/15 22:04, Christophe Lyon wrote:
> On 2 March 2015 at 21:21, Jan Hubicka <hubicka@ucw.cz> wrote:
>>>
>>>
>>> On 01/03/15 16:47, Christophe Lyon wrote:
>>>> On 27 February 2015 at 21:49, Jan Hubicka <hubicka@ucw.cz> wrote:
>>>>>>
>>>>>> ../sysdeps/gnu/siglist.c:72:1: internal compiler error: in address_matters_p, at symtab.c:1908
>>>>>>   versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev, GLIBC_2_3_3);
>>>>>>   ^
>>>>>> 0x66a080 symtab_node::address_matters_p()
>>>>>>          /scratch/sellcey/repos/bootstrap/src/gcc/gcc/symtab.c:1908
>>>>>> 0xe7cbe5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
>>>>>>          /scratch/sellcey/repos/bootstrap/src/gcc/gcc/ipa-icf.c:1443
>>>>>
>>>>> Indeed, the ipa-icf should not try to analyze aliases - just prove ekvialence of
>>>>> definitions they are attached to.  It already does that for functions (bit by accident;
>>>>> it gives up when there is no gimple body), but it does not do that for variables because
>>>>> it gets into ctor_for_folding. For that reason it sometimes decides to try to make two
>>>>> variable aliases alias of each other that is not a good idea, because of possible creation
>>>>> of loops.
>>>>>
>>>>> I am just discussing with Martin the fix.
>>>>>
>>>>> Honza
>>>>
>>>> For the record, I have noticed similar errors on ARM and AArch64
>>>> targets, when building glibc.
>>>>
>>>> Christophe.
>>>>
>>>
>>> I confirm ARM and AArch64 failing to build with this patch:
>>> chmod a-w /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.cT
>>> 0x6b9100 symtab_node::address_matters_p()
>>>        /work/src/gcc/gcc/symtab.c:1908
>>> 0xedb4e5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
>>>        /work/src/gcc/gcc/ipa-icf.c:1723
>>> 0xee03f9 ipa_icf::sem_item_optimizer::merge_classes(unsigned int)
>>>        /work/src/gcc/gcc/ipa-icf.c:2955
>>> 0xee6d31 ipa_icf::sem_item_optimizer::execute()
>>>        /work/src/gcc/gcc/ipa-icf.c:2217
>>> 0xee8df1 ipa_icf_driver
>>>        /work/src/gcc/gcc/ipa-icf.c:3034
>>> 0xee8df1 ipa_icf::pass_ipa_icf::execute(function*)
>>>        /work/src/gcc/gcc/ipa-icf.c:3081
>>
>> I commited patch for the alias merging yesterda night, so it should be fixed
>> now.  If it still fails, please fill in a PR with preprocessed testcase so I
>> can reproduce it in a cross.
>>
>
> On my side, I saw builds complete again starting with r221090, I guess
> that's the commit you are referring to?
Hi,

I built with r221117. I see errors while building following targets:
aarch64_be-none-linux-gnu, aarch64_be-none-linux-gnu,
arm-none-linux-gnueabihf, arm-none-linux-gnueabi.

For aarch64_be-none-linux-gnu I reproduce the error like this:

/work/build-aarch64-none-linux-gnu/install//bin/aarch64-none-linux-gnu-gcc 
/work/src/glibc/sysdeps/gnu/siglist.c -c -std=gnu99 -fgnu89-inline  -O2 
-Wall -Winline -Wundef -Wwrite-strings -fmerge-all-constants 
-frounding-math -g -Wstrict-prototypes   -fno-toplevel-reorder 
-fno-section-anchors       -I/work/src/glibc/include 
-I/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common 
-I/work/build-aarch64-none-linux-gnu/obj/glibc 
-I/work/src/glibc/sysdeps/unix/sysv/linux/aarch64 
-I/work/src/glibc/sysdeps/aarch64/nptl 
-I/work/src/glibc/sysdeps/unix/sysv/linux/generic 
-I/work/src/glibc/sysdeps/unix/sysv/linux/wordsize-64 
-I/work/src/glibc/sysdeps/unix/sysv/linux/include 
-I/work/src/glibc/sysdeps/unix/sysv/linux 
-I/work/src/glibc/sysdeps/nptl  -I/work/src/glibc/sysdeps/pthread 
-I/work/src/glibc/sysdeps/gnu  -I/work/src/glibc/sysdeps/unix/inet 
-I/work/src/glibc/sysdeps/unix/sysv  -I/work/src/glibc/sysdeps/unix 
-I/work/src/glibc/sysdeps/posix  -I/work/src/glibc/sysdeps/aarch64/fpu 
-I/work/src/glibc/sysdeps/aarch64  -I/work/src/glibc/sysdeps/wordsize-64 
  -I/work/src/glibc/sysdeps/ieee754/ldbl-128 
-I/work/src/glibc/sysdeps/ieee754/dbl-64/wordsize-64 
-I/work/src/glibc/sysdeps/ieee754/dbl-64 
-I/work/src/glibc/sysdeps/ieee754/flt-32 
-I/work/src/glibc/sysdeps/aarch64/soft-fp 
-I/work/src/glibc/sysdeps/ieee754  -I/work/src/glibc/sysdeps/generic 
-I/work/src/glibc -I/work/src/glibc/libio -I. -nostdinc -isystem 
/work/build-aarch64-none-linux-gnu/install/bin/../lib/gcc/aarch64-none-linux-gnu/5.0.0/include 
-isystem 
/work/build-aarch64-none-linux-gnu/install/bin/../lib/gcc/aarch64-none-linux-gnu/5.0.0/include-fixed 
-isystem 
/work/build-aarch64-none-linux-gnu/install//aarch64-none-linux-gnu/libc/usr/include 
  -D_LIBC_REENTRANT -include 
/work/build-aarch64-none-linux-gnu/obj/glibc/libc-modules.h 
-DMODULE_NAME=libc -include /work/src/glibc/include/libc-symbols.h 
  -D_IO_MTSAFE_IO -o 
/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/siglist.o -MD 
-MP -MF 
/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/siglist.o.dt 
-MT /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/siglist.o
/work/src/glibc/sysdeps/gnu/siglist.c:77:1: internal compiler error: in 
address_matters_p, at symtab.c:1908
  versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev, GLIBC_2_1);
  ^
0x6b9140 symtab_node::address_matters_p()
	/work/src/gcc/gcc/symtab.c:1908
0xedb685 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
	/work/src/gcc/gcc/ipa-icf.c:1740
0xee05b1 ipa_icf::sem_item_optimizer::merge_classes(unsigned int)
	/work/src/gcc/gcc/ipa-icf.c:2979
0xee6f11 ipa_icf::sem_item_optimizer::execute()
	/work/src/gcc/gcc/ipa-icf.c:2236
0xee902e ipa_icf_driver
	/work/src/gcc/gcc/ipa-icf.c:3061
0xee902e ipa_icf::pass_ipa_icf::execute(function*)
	/work/src/gcc/gcc/ipa-icf.c:3108
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.


I see a related ticket opened recently:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65287

Kind regards,
Alex
>
> Thanks,
>
> Christophe.
>
>> Honza
>>> Please submit a full bug report,
>>> with preprocessed source if appropriate.
>>> Please include the complete backtrace with any bug report.
>>> See <http://gcc.gnu.org/bugs.html> for instructions.
>>> make[2]: ***
>>> [/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/siglist.o]
>>> Error 1
>>> make[2]: *** Waiting for unfinished jobs....
>>> mv -f /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.cT /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.c
>>>
>>> Regards,
>>> Alex
>
Christophe Lyon March 3, 2015, 3:06 p.m. UTC | #13
On 3 March 2015 at 13:44, Alex Velenko <Alex.Velenko@arm.com> wrote:
> On 02/03/15 22:04, Christophe Lyon wrote:
>>
>> On 2 March 2015 at 21:21, Jan Hubicka <hubicka@ucw.cz> wrote:
>>>>
>>>>
>>>>
>>>> On 01/03/15 16:47, Christophe Lyon wrote:
>>>>>
>>>>> On 27 February 2015 at 21:49, Jan Hubicka <hubicka@ucw.cz> wrote:
>>>>>>>
>>>>>>>
>>>>>>> ../sysdeps/gnu/siglist.c:72:1: internal compiler error: in
>>>>>>> address_matters_p, at symtab.c:1908
>>>>>>>   versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev,
>>>>>>> GLIBC_2_3_3);
>>>>>>>   ^
>>>>>>> 0x66a080 symtab_node::address_matters_p()
>>>>>>>          /scratch/sellcey/repos/bootstrap/src/gcc/gcc/symtab.c:1908
>>>>>>> 0xe7cbe5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
>>>>>>>          /scratch/sellcey/repos/bootstrap/src/gcc/gcc/ipa-icf.c:1443
>>>>>>
>>>>>>
>>>>>> Indeed, the ipa-icf should not try to analyze aliases - just prove
>>>>>> ekvialence of
>>>>>> definitions they are attached to.  It already does that for functions
>>>>>> (bit by accident;
>>>>>> it gives up when there is no gimple body), but it does not do that for
>>>>>> variables because
>>>>>> it gets into ctor_for_folding. For that reason it sometimes decides to
>>>>>> try to make two
>>>>>> variable aliases alias of each other that is not a good idea, because
>>>>>> of possible creation
>>>>>> of loops.
>>>>>>
>>>>>> I am just discussing with Martin the fix.
>>>>>>
>>>>>> Honza
>>>>>
>>>>>
>>>>> For the record, I have noticed similar errors on ARM and AArch64
>>>>> targets, when building glibc.
>>>>>
>>>>> Christophe.
>>>>>
>>>>
>>>> I confirm ARM and AArch64 failing to build with this patch:
>>>> chmod a-w
>>>> /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.cT
>>>> 0x6b9100 symtab_node::address_matters_p()
>>>>        /work/src/gcc/gcc/symtab.c:1908
>>>> 0xedb4e5 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
>>>>        /work/src/gcc/gcc/ipa-icf.c:1723
>>>> 0xee03f9 ipa_icf::sem_item_optimizer::merge_classes(unsigned int)
>>>>        /work/src/gcc/gcc/ipa-icf.c:2955
>>>> 0xee6d31 ipa_icf::sem_item_optimizer::execute()
>>>>        /work/src/gcc/gcc/ipa-icf.c:2217
>>>> 0xee8df1 ipa_icf_driver
>>>>        /work/src/gcc/gcc/ipa-icf.c:3034
>>>> 0xee8df1 ipa_icf::pass_ipa_icf::execute(function*)
>>>>        /work/src/gcc/gcc/ipa-icf.c:3081
>>>
>>>
>>> I commited patch for the alias merging yesterda night, so it should be
>>> fixed
>>> now.  If it still fails, please fill in a PR with preprocessed testcase
>>> so I
>>> can reproduce it in a cross.
>>>
>>
>> On my side, I saw builds complete again starting with r221090, I guess
>> that's the commit you are referring to?
>
> Hi,
>
> I built with r221117. I see errors while building following targets:
> aarch64_be-none-linux-gnu, aarch64_be-none-linux-gnu,
> arm-none-linux-gnueabihf, arm-none-linux-gnueabi.

Indeed, it's broken again since r221099.

>
> For aarch64_be-none-linux-gnu I reproduce the error like this:
>
> /work/build-aarch64-none-linux-gnu/install//bin/aarch64-none-linux-gnu-gcc
> /work/src/glibc/sysdeps/gnu/siglist.c -c -std=gnu99 -fgnu89-inline  -O2
> -Wall -Winline -Wundef -Wwrite-strings -fmerge-all-constants -frounding-math
> -g -Wstrict-prototypes   -fno-toplevel-reorder -fno-section-anchors
> -I/work/src/glibc/include
> -I/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common
> -I/work/build-aarch64-none-linux-gnu/obj/glibc
> -I/work/src/glibc/sysdeps/unix/sysv/linux/aarch64
> -I/work/src/glibc/sysdeps/aarch64/nptl
> -I/work/src/glibc/sysdeps/unix/sysv/linux/generic
> -I/work/src/glibc/sysdeps/unix/sysv/linux/wordsize-64
> -I/work/src/glibc/sysdeps/unix/sysv/linux/include
> -I/work/src/glibc/sysdeps/unix/sysv/linux -I/work/src/glibc/sysdeps/nptl
> -I/work/src/glibc/sysdeps/pthread -I/work/src/glibc/sysdeps/gnu
> -I/work/src/glibc/sysdeps/unix/inet -I/work/src/glibc/sysdeps/unix/sysv
> -I/work/src/glibc/sysdeps/unix -I/work/src/glibc/sysdeps/posix
> -I/work/src/glibc/sysdeps/aarch64/fpu -I/work/src/glibc/sysdeps/aarch64
> -I/work/src/glibc/sysdeps/wordsize-64
> -I/work/src/glibc/sysdeps/ieee754/ldbl-128
> -I/work/src/glibc/sysdeps/ieee754/dbl-64/wordsize-64
> -I/work/src/glibc/sysdeps/ieee754/dbl-64
> -I/work/src/glibc/sysdeps/ieee754/flt-32
> -I/work/src/glibc/sysdeps/aarch64/soft-fp -I/work/src/glibc/sysdeps/ieee754
> -I/work/src/glibc/sysdeps/generic -I/work/src/glibc -I/work/src/glibc/libio
> -I. -nostdinc -isystem
> /work/build-aarch64-none-linux-gnu/install/bin/../lib/gcc/aarch64-none-linux-gnu/5.0.0/include
> -isystem
> /work/build-aarch64-none-linux-gnu/install/bin/../lib/gcc/aarch64-none-linux-gnu/5.0.0/include-fixed
> -isystem
> /work/build-aarch64-none-linux-gnu/install//aarch64-none-linux-gnu/libc/usr/include
> -D_LIBC_REENTRANT -include
> /work/build-aarch64-none-linux-gnu/obj/glibc/libc-modules.h
> -DMODULE_NAME=libc -include /work/src/glibc/include/libc-symbols.h
> -D_IO_MTSAFE_IO -o
> /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/siglist.o -MD -MP
> -MF /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/siglist.o.dt
> -MT /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/siglist.o
> /work/src/glibc/sysdeps/gnu/siglist.c:77:1: internal compiler error: in
> address_matters_p, at symtab.c:1908
>  versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev, GLIBC_2_1);
>  ^
> 0x6b9140 symtab_node::address_matters_p()
>         /work/src/gcc/gcc/symtab.c:1908
> 0xedb685 ipa_icf::sem_variable::merge(ipa_icf::sem_item*)
>         /work/src/gcc/gcc/ipa-icf.c:1740
> 0xee05b1 ipa_icf::sem_item_optimizer::merge_classes(unsigned int)
>         /work/src/gcc/gcc/ipa-icf.c:2979
> 0xee6f11 ipa_icf::sem_item_optimizer::execute()
>         /work/src/gcc/gcc/ipa-icf.c:2236
> 0xee902e ipa_icf_driver
>         /work/src/gcc/gcc/ipa-icf.c:3061
> 0xee902e ipa_icf::pass_ipa_icf::execute(function*)
>         /work/src/gcc/gcc/ipa-icf.c:3108
> Please submit a full bug report,
> with preprocessed source if appropriate.
> Please include the complete backtrace with any bug report.
> See <http://gcc.gnu.org/bugs.html> for instructions.
>
>
> I see a related ticket opened recently:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65287
>
> Kind regards,
> Alex
>
>>
>> Thanks,
>>
>> Christophe.
>>
>>> Honza
>>>>
>>>> Please submit a full bug report,
>>>> with preprocessed source if appropriate.
>>>> Please include the complete backtrace with any bug report.
>>>> See <http://gcc.gnu.org/bugs.html> for instructions.
>>>> make[2]: ***
>>>> [/work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/siglist.o]
>>>> Error 1
>>>> make[2]: *** Waiting for unfinished jobs....
>>>> mv -f
>>>> /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.cT
>>>> /work/build-aarch64-none-linux-gnu/obj/glibc/stdio-common/errlist-compat.c
>>>>
>>>> Regards,
>>>> Alex
>>
>>
>
Jan Hubicka March 3, 2015, 8:01 p.m. UTC | #14
> > Hi,
> >
> > I built with r221117. I see errors while building following targets:
> > aarch64_be-none-linux-gnu, aarch64_be-none-linux-gnu,
> > arm-none-linux-gnueabihf, arm-none-linux-gnueabi.
> 
> Indeed, it's broken again since r221099.

Accidentally I reverted the var->alias check (probably while merging patches from mainline).
It should be fixed again now by:

2015-03-03  Martin Liska  <mliska@suse.cz>                                      
                                                                                
        PR ipa/65287                                                            
        * ipa-icf.c (sem_variable::parse): Skip all alias variables.            

Sorry for that.

Honza
Christophe Lyon March 4, 2015, 9:11 a.m. UTC | #15
On 3 March 2015 at 21:01, Jan Hubicka <hubicka@ucw.cz> wrote:
>> > Hi,
>> >
>> > I built with r221117. I see errors while building following targets:
>> > aarch64_be-none-linux-gnu, aarch64_be-none-linux-gnu,
>> > arm-none-linux-gnueabihf, arm-none-linux-gnueabi.
>>
>> Indeed, it's broken again since r221099.
>
> Accidentally I reverted the var->alias check (probably while merging patches from mainline).
> It should be fixed again now by:
>
> 2015-03-03  Martin Liska  <mliska@suse.cz>
>
>         PR ipa/65287
>         * ipa-icf.c (sem_variable::parse): Skip all alias variables.
>
> Sorry for that.
>
Indeed, it's OK now.
Thanks.

> Honza
diff mbox

Patch

Index: symtab.c
===================================================================
--- symtab.c	(revision 221034)
+++ symtab.c	(working copy)
@@ -1156,7 +1156,11 @@  symtab_node::make_decl_local (void)
     return;
 
   if (TREE_CODE (decl) == VAR_DECL)
-    DECL_COMMON (decl) = 0;
+    {
+      DECL_COMMON (decl) = 0;
+      /* ADDRESSABLE flag is not defined for public symbols.  */
+      TREE_ADDRESSABLE (decl) = 1;
+    }
   else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
 
   DECL_COMDAT (decl) = 0;
@@ -1513,6 +1517,19 @@  symtab_node::resolve_alias (symtab_node
   /* If alias has address taken, so does the target.  */
   if (address_taken)
     target->ultimate_alias_target ()->address_taken = true;
+
+  /* All non-weakref aliases of THIS are now in fact aliases of TARGET.  */
+  ipa_ref *ref;
+  for (unsigned i = 0; iterate_direct_aliases (i, ref);)
+    {
+      struct symtab_node *alias_alias = ref->referring;
+      if (!alias_alias->weakref)
+	{
+	  alias_alias->remove_all_references ();
+	  alias_alias->create_reference (target, IPA_REF_ALIAS, NULL);
+	}
+      else i++;
+    }
   return true;
 }
 
@@ -1863,3 +1880,31 @@  symtab_node::call_for_symbol_and_aliases
     }
   return false;
 }
+
+/* Return ture if address of N is possibly compared.  */
+
+static bool
+address_matters_1 (symtab_node *n, void *)
+{
+  struct ipa_ref *ref;
+
+  if (!n->address_can_be_compared_p ())
+    return false;
+  if (n->externally_visible || n->force_output)
+    return true;
+
+  for (unsigned int i = 0; n->iterate_referring (i, ref); i++)
+    if (ref->address_matters_p ())
+      return true;
+  return false;
+}
+
+/* Return true if symbol's address may possibly be compared to other
+   symbol's address.  */
+
+bool
+symtab_node::address_matters_p ()
+{
+  gcc_assert (!alias);
+  return call_for_symbol_and_aliases (address_matters_1, NULL, true);
+}
Index: common.opt
===================================================================
--- common.opt	(revision 221034)
+++ common.opt	(working copy)
@@ -1644,11 +1644,11 @@  Report on permanent memory allocation in
 ; string constants and constants from constant pool, if 2 also constant
 ; variables.
 fmerge-all-constants
-Common Report Var(flag_merge_constants,2) Init(1) Optimization
+Common Report Var(flag_merge_constants,2) Init(1)
 Attempt to merge identical constants and constant variables
 
 fmerge-constants
-Common Report Var(flag_merge_constants,1) Optimization
+Common Report Var(flag_merge_constants,1)
 Attempt to merge identical constants across compilation units
 
 fmerge-debug-strings
Index: testsuite/gcc.dg/pr64454.c
===================================================================
--- testsuite/gcc.dg/pr64454.c	(revision 221034)
+++ testsuite/gcc.dg/pr64454.c	(working copy)
@@ -1,6 +1,6 @@ 
 /* PR tree-optimization/64454 */
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fdump-tree-vrp1 -fno-ipa-icf" } */
 
 unsigned
 f1 (unsigned x)
Index: testsuite/gcc.dg/pr28685-1.c
===================================================================
--- testsuite/gcc.dg/pr28685-1.c	(revision 221034)
+++ testsuite/gcc.dg/pr28685-1.c	(working copy)
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" }  */
+/* { dg-options "-O2 -fdump-tree-optimized -fno-ipa-icf" }  */
 
 /* Should produce <=.  */
 int test1 (int a, int b)
Index: testsuite/gcc.dg/ipa/iinline-5.c
===================================================================
--- testsuite/gcc.dg/ipa/iinline-5.c	(revision 221034)
+++ testsuite/gcc.dg/ipa/iinline-5.c	(working copy)
@@ -1,7 +1,7 @@ 
 /* Verify that simple indirect calls are inlined even without early
    inlining..  */
 /* { dg-do run } */
-/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining"  } */
+/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-icf"  } */
 
 extern void abort (void);
 
Index: testsuite/g++.dg/warn/Wsuggest-final.C
===================================================================
--- testsuite/g++.dg/warn/Wsuggest-final.C	(revision 221034)
+++ testsuite/g++.dg/warn/Wsuggest-final.C	(working copy)
@@ -1,8 +1,9 @@ 
 // { dg-do compile }
 // { dg-options "-O2 -Wsuggest-final-types -Wsuggest-final-methods" }
+int c;
 struct A { // { dg-warning "final would enable devirtualization of 4 calls" }
 virtual void a() {} // { dg-warning "final would enable devirtualization of 2 calls" }
- virtual void b() {} // { dg-warning "final would enable devirtualization of 2 calls"  }
+ virtual void b() {c++;} // { dg-warning "final would enable devirtualization of 2 calls"  }
 };
 void
 t(struct A *a)
Index: testsuite/g++.dg/ipa/ipa-icf-4.C
===================================================================
--- testsuite/g++.dg/ipa/ipa-icf-4.C	(revision 221034)
+++ testsuite/g++.dg/ipa/ipa-icf-4.C	(working copy)
@@ -43,6 +43,6 @@  int main()
   return 123;
 }
 
-/* { dg-final { scan-ipa-dump "\(Varpool alias has been created\)|\(Symbol aliases are not supported by target\)" "icf"  } } */
+/* { dg-final { scan-ipa-dump "\(Unified; Variable alias has been created\)|\(Symbol aliases are not supported by target\)" "icf"  } } */
 /* { dg-final { scan-ipa-dump "Equal symbols: 6" "icf"  } } */
 /* { dg-final { cleanup-ipa-dump "icf" } } */
Index: ipa-ref.c
===================================================================
--- ipa-ref.c	(revision 221034)
+++ ipa-ref.c	(working copy)
@@ -124,23 +124,3 @@  ipa_ref::referred_ref_list (void)
 {
   return &referred->ref_list;
 }
-
-/* Return true if refernece may be used in address compare.  */
-bool
-ipa_ref::address_matters_p ()
-{
-  if (use != IPA_REF_ADDR)
-    return false;
-  /* Addresses taken from virtual tables are never compared.  */
-  if (is_a <varpool_node *> (referring)
-      && DECL_VIRTUAL_P (referring->decl))
-    return false;
-  /* Address of virtual tables and functions is never compared.  */
-  if (DECL_VIRTUAL_P (referred->decl))
-    return false;
-  /* Address of C++ cdtors is never compared.  */
-  if (is_a <cgraph_node *> (referred)
-      && (DECL_CXX_CONSTRUCTOR_P (referred->decl) || DECL_CXX_DESTRUCTOR_P (referred->decl)))
-    return false;
-  return true;
-}
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 221034)
+++ cgraph.c	(working copy)
@@ -2630,7 +2630,7 @@  cgraph_edge::verify_corresponds_to_fndec
   if (!node
       || node->body_removed
       || node->in_other_partition
-      || node->icf_merged
+      || callee->icf_merged
       || callee->in_other_partition)
     return false;
 
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 221034)
+++ cgraph.h	(working copy)
@@ -326,9 +326,6 @@  public:
   /* Return true if ONE and TWO are part of the same COMDAT group.  */
   inline bool in_same_comdat_group_p (symtab_node *target);
 
-  /* Return true when there is a reference to node and it is not vtable.  */
-  bool address_taken_from_non_vtable_p (void);
-
   /* Return true if symbol is known to be nonzero.  */
   bool nonzero_address ();
 
@@ -337,6 +334,15 @@  public:
      return 2 otherwise.   */
   int equal_address_to (symtab_node *s2);
 
+  /* Return true if symbol's address may possibly be compared to other
+     symbol's address.  */
+  bool address_matters_p ();
+
+  /* Return true if NODE's address can be compared.  This use properties
+     of NODE only and does not look if the address is actually taken in
+     interesting way.  For that use ADDRESS_MATTERS_P instead.  */
+  bool address_can_be_compared_p (void);
+
   /* Return symbol table node associated with DECL, if any,
      and NULL otherwise.  */
   static inline symtab_node *get (const_tree decl)
@@ -3022,6 +3028,43 @@  varpool_node::call_for_symbol_and_aliase
   return false;
 }
 
+/* Return true if NODE's address can be compared.  */
+
+inline bool
+symtab_node::address_can_be_compared_p ()
+{
+  /* Address of virtual tables and functions is never compared.  */
+  if (DECL_VIRTUAL_P (decl))
+    return false;
+  /* Address of C++ cdtors is never compared.  */
+  if (is_a <cgraph_node *> (this)
+      && (DECL_CXX_CONSTRUCTOR_P (decl)
+	  || DECL_CXX_DESTRUCTOR_P (decl)))
+    return false;
+  /* Constant pool symbols addresses are never compared.
+     flag_merge_constants permits us to assume the same on readonly vars.  */
+  if (is_a <varpool_node *> (this)
+      && (DECL_IN_CONSTANT_POOL (decl)
+	  || (flag_merge_constants >= 2
+	      && TREE_READONLY (decl) && !TREE_THIS_VOLATILE (decl))))
+    return false;
+  return true;
+}
+
+/* Return true if refernece may be used in address compare.  */
+
+inline bool
+ipa_ref::address_matters_p ()
+{
+  if (use != IPA_REF_ADDR)
+    return false;
+  /* Addresses taken from virtual tables are never compared.  */
+  if (is_a <varpool_node *> (referring)
+      && DECL_VIRTUAL_P (referring->decl))
+    return false;
+  return referred->address_can_be_compared_p ();
+}
+
 /* Build polymorphic call context for indirect call E.  */
 
 inline
Index: ipa-visibility.c
===================================================================
--- ipa-visibility.c	(revision 221034)
+++ ipa-visibility.c	(working copy)
@@ -129,27 +129,6 @@  cgraph_node::local_p (void)
 					
 }
 
-/* Return true when there is a reference to node and it is not vtable.  */
-
-bool
-symtab_node::address_taken_from_non_vtable_p (void)
-{
-  int i;
-  struct ipa_ref *ref = NULL;
-
-  for (i = 0; iterate_referring (i, ref); i++)
-    if (ref->use == IPA_REF_ADDR)
-      {
-	varpool_node *node;
-	if (is_a <cgraph_node *> (ref->referring))
-	  return true;
-	node = dyn_cast <varpool_node *> (ref->referring);
-	if (!DECL_VIRTUAL_P (node->decl))
-	  return true;
-      }
-  return false;
-}
-
 /* A helper for comdat_can_be_unshared_p.  */
 
 static bool
@@ -157,16 +136,14 @@  comdat_can_be_unshared_p_1 (symtab_node
 {
   if (!node->externally_visible)
     return true;
-  /* When address is taken, we don't know if equality comparison won't
-     break eventually. Exception are virutal functions, C++
-     constructors/destructors and vtables, where this is not possible by
-     language standard.  */
-  if (!DECL_VIRTUAL_P (node->decl)
-      && (TREE_CODE (node->decl) != FUNCTION_DECL
-	  || (!DECL_CXX_CONSTRUCTOR_P (node->decl)
-	      && !DECL_CXX_DESTRUCTOR_P (node->decl)))
-      && node->address_taken_from_non_vtable_p ())
-    return false;
+  if (node->address_can_be_compared_p ())
+    {
+      struct ipa_ref *ref;
+
+      for (unsigned int i = 0; node->iterate_referring (i, ref); i++)
+	if (ref->address_matters_p ())
+	  return false;
+    }
 
   /* If the symbol is used in some weird way, better to not touch it.  */
   if (node->force_output)
@@ -387,7 +364,8 @@  can_replace_by_local_alias_in_vtable (sy
 /* walk_tree callback that rewrites initializer references.   */
 
 static tree
-update_vtable_references (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
+update_vtable_references (tree *tp, int *walk_subtrees,
+			  void *data ATTRIBUTE_UNUSED)
 {
   if (TREE_CODE (*tp) == VAR_DECL
       || TREE_CODE (*tp) == FUNCTION_DECL)
Index: cgraphunit.c
===================================================================
--- cgraphunit.c	(revision 221034)
+++ cgraphunit.c	(working copy)
@@ -2468,6 +2468,7 @@  cgraph_node::create_wrapper (cgraph_node
   release_body (true);
   reset ();
 
+  DECL_UNINLINABLE (decl) = false;
   DECL_RESULT (decl) = decl_result;
   DECL_INITIAL (decl) = NULL;
   allocate_struct_function (decl, false);
Index: ipa-icf.c
===================================================================
--- ipa-icf.c	(revision 221034)
+++ ipa-icf.c	(working copy)
@@ -147,7 +147,7 @@  symbol_compare_collection::symbol_compar
 
       if (ref->referred->get_availability () <= AVAIL_INTERPOSABLE)
         {
-	  if (ref->use == IPA_REF_ADDR)
+	  if (ref->address_matters_p ())
 	    m_references.safe_push (ref->referred);
 	  else
 	    m_interposables.safe_push (ref->referred);
@@ -632,8 +633,56 @@  set_local (cgraph_node *node, void *data
   return false;
 }
 
+/* TREE_ADDRESSABLE of NODE to true if DATA is non-NULL.
+   Helper for call_for_symbol_thunks_and_aliases.  */
+
+static bool
+set_addressable (varpool_node *node, void *)
+{
+  TREE_ADDRESSABLE (node->decl) = 1;
+  return false;
+}
+
+/* Redirect all callers of N and its aliases to TO.  Remove aliases if
+   possible.  Return number of redirections made.  */
+
+static int
+redirect_all_callers (cgraph_node *n, cgraph_node *to)
+{
+  int nredirected = 0;
+  ipa_ref *ref;
+
+  while (n->callers)
+    {
+      cgraph_edge *e = n->callers;
+      e->redirect_callee (to);
+      nredirected++;
+    }
+  for (unsigned i = 0; n->iterate_direct_aliases (i, ref);)
+    {
+      bool removed = false;
+      cgraph_node *n_alias = dyn_cast <cgraph_node *> (ref->referring);
+
+      if ((DECL_COMDAT_GROUP (n->decl)
+	   && (DECL_COMDAT_GROUP (n->decl)
+	       == DECL_COMDAT_GROUP (n_alias->decl)))
+	  || (n_alias->get_availability () > AVAIL_INTERPOSABLE
+	      && n->get_availability () > AVAIL_INTERPOSABLE))
+	{
+	  nredirected += redirect_all_callers (n_alias, to);
+	  if (n_alias->can_remove_if_no_direct_calls_p ()
+	      && !n_alias->has_aliases_p ())
+	    n_alias->remove ();
+	}
+      if (!removed)
+	i++;
+    }
+  return nredirected;
+}
+
 /* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can
    be applied.  */
+
 bool
 sem_function::merge (sem_item *alias_item)
 {
@@ -642,16 +691,29 @@  sem_function::merge (sem_item *alias_ite
   sem_function *alias_func = static_cast<sem_function *> (alias_item);
 
   cgraph_node *original = get_node ();
-  cgraph_node *local_original = original;
+  cgraph_node *local_original = NULL;
   cgraph_node *alias = alias_func->get_node ();
-  bool original_address_matters;
-  bool alias_address_matters;
 
-  bool create_thunk = false;
+  bool create_wrapper = false;
   bool create_alias = false;
   bool redirect_callers = false;
+  bool remove = false;
+
   bool original_discardable = false;
 
+  bool original_address_matters = original->address_matters_p ();
+  bool alias_address_matters = alias->address_matters_p ();
+
+  if (DECL_NO_INLINE_WARNING_P (original->decl)
+      != DECL_NO_INLINE_WARNING_P (alias->decl))
+    {
+      if (dump_file)
+	fprintf (dump_file,
+		 "Not unifying; "
+		 "DECL_NO_INLINE_WARNING mismatch.\n\n");
+      return false;
+    }
+
   /* Do not attempt to mix functions from different user sections;
      we do not know what user intends with those.  */
   if (((DECL_SECTION_NAME (original->decl) && !original->implicit_section)
@@ -660,123 +722,173 @@  sem_function::merge (sem_item *alias_ite
     {
       if (dump_file)
 	fprintf (dump_file,
-		 "Not unifying; original and alias are in different sections.\n\n");
+		 "Not unifying; "
+		 "original and alias are in different sections.\n\n");
       return false;
     }
 
   /* See if original is in a section that can be discarded if the main
-     symbol is not used.  */
-  if (DECL_EXTERNAL (original->decl))
-    original_discardable = true;
-  if (original->resolution == LDPR_PREEMPTED_REG
-      || original->resolution == LDPR_PREEMPTED_IR)
-    original_discardable = true;
-  if (original->can_be_discarded_p ())
+     symbol is not used.
+
+     Also consider case where we have resolution info and we know that
+     original's definition is not going to be used.  In this case we can not
+     create alias to original.  */
+  if (original->can_be_discarded_p ()
+      || (node->resolution != LDPR_UNKNOWN
+	  && !decl_binds_to_current_def_p (node->decl)))
     original_discardable = true;
 
-  /* See if original and/or alias address can be compared for equality.  */
-  original_address_matters
-    = (!DECL_VIRTUAL_P (original->decl)
-       && (original->externally_visible
-	   || original->address_taken_from_non_vtable_p ()));
-  alias_address_matters
-    = (!DECL_VIRTUAL_P (alias->decl)
-       && (alias->externally_visible
-	   || alias->address_taken_from_non_vtable_p ()));
-
-  /* If alias and original can be compared for address equality, we need
-     to create a thunk.  Also we can not create extra aliases into discardable
-     section (or we risk link failures when section is discarded).  */
-  if ((original_address_matters
-       && alias_address_matters)
+  /* Creating a symtab alias is the optimal way to merge.
+     It however can not be used in the following cases:
+
+     1) if ORIGINAL and ALIAS may be possibly compared for address equality.
+     2) if ORIGINAL is in a section that may be discarded by linker or if
+	it is an external functions where we can not create an alias
+	(ORIGINAL_DISCARDABLE)
+     3) if target do not support symbol aliases.
+
+     If we can not produce alias, we will turn ALIAS into WRAPPER of ORIGINAL
+     and/or redirect all callers from ALIAS to ORIGINAL.  */
+  if ((original_address_matters && alias_address_matters)
       || original_discardable
-      || DECL_COMDAT_GROUP (alias->decl)
       || !sem_item::target_supports_symbol_aliases_p ())
     {
-      create_thunk = !stdarg_p (TREE_TYPE (alias->decl));
-      create_alias = false;
-      /* When both alias and original are not overwritable, we can save
-         the extra thunk wrapper for direct calls.  */
+      /* First see if we can produce wrapper.  */
+
+      /* Do not turn function in one comdat group into wrapper to another
+	 comdat group. Other compiler producing the body of the
+	 another comdat group may make opossite decision and with unfortunate
+	 linker choices this may close a loop.  */
+      if (DECL_COMDAT_GROUP (alias->decl)
+	  && (DECL_COMDAT_GROUP (alias->decl)
+	      != DECL_COMDAT_GROUP (original->decl)))
+	{
+	  if (dump_file)
+	    fprintf (dump_file,
+		     "Wrapper cannot be created because of COMDAT\n");
+	}
+      else if (DECL_STATIC_CHAIN (alias->decl))
+        {
+	  if (dump_file)
+	    fprintf (dump_file,
+		     "Can not create wrapper of nested functions.\n");
+        }
+      /* TODO: We can also deal with variadic functions never calling
+	 VA_START.  */
+      else if (stdarg_p (TREE_TYPE (alias->decl)))
+	{
+	  if (dump_file)
+	    fprintf (dump_file,
+		     "can not create wrapper of stdarg function.\n");
+	}
+      else if (inline_summaries
+	       && inline_summaries->get (alias)->self_size <= 2)
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Wrapper creation is not "
+		     "profitable (function is too small).\n");
+	}
+      /* If user paid attention to mark function noinline, assume it is
+	 somewhat special and do not try to turn it into a wrapper that can
+	 not be undone by inliner.  */
+      else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (alias->decl)))
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Wrappers are not created for noinline.\n");
+	}
+      else
+        create_wrapper = true;
+
+      /* We can redirect local calls in the case both alias and orignal
+	 are not interposable.  */
       redirect_callers
-	= (!original_discardable
-	   && !DECL_COMDAT_GROUP (alias->decl)
-	   && alias->get_availability () > AVAIL_INTERPOSABLE
-	   && original->get_availability () > AVAIL_INTERPOSABLE
-	   && !alias->instrumented_version);
-    }
-  else
-    {
-      create_alias = true;
-      create_thunk = false;
-      redirect_callers = false;
-    }
+	= alias->get_availability () > AVAIL_INTERPOSABLE
+	  && original->get_availability () > AVAIL_INTERPOSABLE
+	  && !alias->instrumented_version;
 
-  /* We want thunk to always jump to the local function body
-     unless the body is comdat and may be optimized out.  */
-  if ((create_thunk || redirect_callers)
-      && (!original_discardable
+      if (!redirect_callers && !create_wrapper)
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Not unifying; can not redirect callers nor "
+		     "produce wrapper\n\n");
+	  return false;
+	}
+
+      /* Work out the symbol the wrapper should call.
+	 If ORIGINAL is interposable, we need to call a local alias.
+	 Also produce local alias (if possible) as an optimization.  */
+      if (!original_discardable
 	  || (DECL_COMDAT_GROUP (original->decl)
 	      && (DECL_COMDAT_GROUP (original->decl)
-		  == DECL_COMDAT_GROUP (alias->decl)))))
-    local_original
-      = dyn_cast <cgraph_node *> (original->noninterposable_alias ());
-
-    if (!local_original)
-      {
-	if (dump_file)
-	  fprintf (dump_file, "Noninterposable alias cannot be created.\n\n");
-
-	return false;
-      }
+		  == DECL_COMDAT_GROUP (alias->decl))))
+	{
+	  local_original
+	    = dyn_cast <cgraph_node *> (original->noninterposable_alias ());
+	  if (!local_original
+	      && original->get_availability () > AVAIL_INTERPOSABLE)
+	    local_original = original;
+	  /* If original is COMDAT local, we can not really redirect external
+	     callers to it.  */
+	  if (original->comdat_local_p ())
+	    redirect_callers = false;
+	}
+      /* If we can not use local alias, fallback to the original
+	 when possible.  */
+      else if (original->get_availability () > AVAIL_INTERPOSABLE)
+	local_original = original;
+      if (!local_original)
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Not unifying; "
+		     "can not produce local alias.\n\n");
+	  return false;
+	}
 
-  if (!decl_binds_to_current_def_p (alias->decl))
-    {
-      if (dump_file)
-	fprintf (dump_file, "Declaration does not bind to currect definition.\n\n");
-      return false;
+      if (!redirect_callers && !create_wrapper)
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Not unifying; "
+		     "can not redirect callers nor produce a wrapper\n\n");
+	  return false;
+	}
+      if (!create_wrapper
+	  && !alias->can_remove_if_no_direct_calls_p ())
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Not unifying; can not make wrapper and "
+		     "function has other uses than direct calls\n\n");
+	  return false;
+	}
     }
+  else
+    create_alias = true;
 
   if (redirect_callers)
     {
-      /* If alias is non-overwritable then
-         all direct calls are safe to be redirected to the original.  */
-      bool redirected = false;
-      while (alias->callers)
-	{
-	  cgraph_edge *e = alias->callers;
-	  e->redirect_callee (local_original);
-	  push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
+      int nredirected = redirect_all_callers (alias, local_original);
 
-	  if (e->call_stmt)
-	    e->redirect_call_stmt_to_callee ();
+      if (nredirected)
+	{
+	  alias->icf_merged = true;
+	  local_original->icf_merged = true;
 
-	  pop_cfun ();
-	  redirected = true;
+	  if (dump_file && nredirected)
+	    fprintf (dump_file, "%i local calls have been "
+		     "redirected.\n", nredirected);
 	}
 
-      alias->icf_merged = true;
-      if (local_original->lto_file_data
-	  && alias->lto_file_data
-	  && local_original->lto_file_data != alias->lto_file_data)
-      local_original->merged = true;
-
-      /* The alias function is removed if symbol address
-         does not matter.  */
-      if (!alias_address_matters)
-	alias->remove ();
-
-      if (dump_file && redirected)
-	fprintf (dump_file, "Callgraph local calls have been redirected.\n\n");
+      /* If all callers was redirected, do not produce wrapper.  */
+      if (alias->can_remove_if_no_direct_calls_p ()
+	  && !alias->has_aliases_p ())
+	{
+	  create_wrapper = false;
+	  remove = true;
+	}
+      gcc_assert (!create_alias);
     }
-  /* If the condtion above is not met, we are lucky and can turn the
-     function into real alias.  */
   else if (create_alias)
     {
       alias->icf_merged = true;
-      if (local_original->lto_file_data
-	  && alias->lto_file_data
-	  && local_original->lto_file_data != alias->lto_file_data)
-      local_original->merged = true;
 
       /* Remove the function's body.  */
       ipa_merge_profiles (original, alias);
@@ -791,39 +903,38 @@  sem_function::merge (sem_item *alias_ite
 	 (set_local, (void *)(size_t) original->local_p (), true);
 
       if (dump_file)
-	fprintf (dump_file, "Callgraph alias has been created.\n\n");
+	fprintf (dump_file, "Unified; Function alias has been created.\n\n");
     }
-  else if (create_thunk)
+  if (create_wrapper)
     {
-      if (DECL_COMDAT_GROUP (alias->decl))
-	{
-	  if (dump_file)
-	    fprintf (dump_file, "Callgraph thunk cannot be created because of COMDAT\n");
+      gcc_assert (!create_alias);
+      alias->icf_merged = true;
+      local_original->icf_merged = true;
 
-	  return 0;
-	}
+      ipa_merge_profiles (local_original, alias, true);
+      alias->create_wrapper (local_original);
 
-      if (DECL_STATIC_CHAIN (alias->decl))
-        {
-         if (dump_file)
-           fprintf (dump_file, "Thunk creation is risky for static-chain functions.\n\n");
+      if (dump_file)
+	fprintf (dump_file, "Unified; Wrapper has been created.\n\n");
+    }
+  gcc_assert (alias->icf_merged || remove);
+  original->icf_merged = true;
 
-         return 0;
-        }
+  /* Inform the inliner about cross-module merging.  */
+  if ((original->lto_file_data || alias->lto_file_data)
+      && original->lto_file_data != alias->lto_file_data)
+    local_original->merged = original->merged = true;
 
+  if (remove)
+    {
+      ipa_merge_profiles (original, alias);
+      alias->release_body ();
+      alias->reset ();
+      alias->body_removed = true;
       alias->icf_merged = true;
-      if (local_original->lto_file_data
-	  && alias->lto_file_data
-	  && local_original->lto_file_data != alias->lto_file_data)
-      local_original->merged = true;
-      ipa_merge_profiles (local_original, alias, true);
-      alias->create_wrapper (local_original);
-
       if (dump_file)
-	fprintf (dump_file, "Callgraph thunk has been created.\n\n");
+	fprintf (dump_file, "Unified; Function body was removed.\n");
     }
-  else if (dump_file)
-    fprintf (dump_file, "Callgraph merge operation cannot be performed.\n\n");
 
   return true;
 }
@@ -1319,7 +1430,8 @@  sem_variable::merge (sem_item *alias_ite
   if (!sem_item::target_supports_symbol_aliases_p ())
     {
       if (dump_file)
-	fprintf (dump_file, "Symbol aliases are not supported by target\n\n");
+	fprintf (dump_file, "Not unifying; "
+		 "Symbol aliases are not supported by target\n\n");
       return false;
     }
 
@@ -1329,73 +1441,94 @@  sem_variable::merge (sem_item *alias_ite
   varpool_node *alias = alias_var->get_node ();
   bool original_discardable = false;
 
+  bool original_address_matters = original->address_matters_p ();
+  bool alias_address_matters = alias->address_matters_p ();
+
   /* See if original is in a section that can be discarded if the main
-     symbol is not used.  */
-  if (DECL_EXTERNAL (original->decl))
-    original_discardable = true;
-  if (original->resolution == LDPR_PREEMPTED_REG
-      || original->resolution == LDPR_PREEMPTED_IR)
-    original_discardable = true;
-  if (original->can_be_discarded_p ())
+     symbol is not used.
+     Also consider case where we have resolution info and we know that
+     original's definition is not going to be used.  In this case we can not
+     create alias to original.  */
+  if (original->can_be_discarded_p ()
+      || (node->resolution != LDPR_UNKNOWN
+	  && !decl_binds_to_current_def_p (node->decl)))
     original_discardable = true;
 
   gcc_assert (!TREE_ASM_WRITTEN (alias->decl));
 
-  if (original_discardable || DECL_EXTERNAL (alias_var->decl) ||
-      !compare_sections (alias_var))
+  /* Constant pool machinery is not quite ready for aliases.
+     TODO: varasm code contains logic for merging DECL_IN_CONSTANT_POOL.
+     For LTO merging does not happen that is an important missing feature.
+     We can enable merging with LTO if the DECL_IN_CONSTANT_POOL
+     flag is dropped and non-local symbol name is assigned.  */
+  if (DECL_IN_CONSTANT_POOL (alias->decl)
+      || DECL_IN_CONSTANT_POOL (original->decl))
     {
       if (dump_file)
-	fprintf (dump_file, "Varpool alias cannot be created\n\n");
+	fprintf (dump_file,
+		 "Not unifying; constant pool variables.\n\n");
+      return false;
+    }
 
+  /* Do not attempt to mix functions from different user sections;
+     we do not know what user intends with those.  */
+  if (((DECL_SECTION_NAME (original->decl) && !original->implicit_section)
+       || (DECL_SECTION_NAME (alias->decl) && !alias->implicit_section))
+      && DECL_SECTION_NAME (original->decl) != DECL_SECTION_NAME (alias->decl))
+    {
+      if (dump_file)
+	fprintf (dump_file,
+		 "Not unifying; "
+		 "original and alias are in different sections.\n\n");
       return false;
     }
-  else
+
+  /* We can not merge if address comparsion metters.  */
+  if (original_address_matters && alias_address_matters
+      && flag_merge_constants < 2)
     {
-      // alias cycle creation check
-      varpool_node *n = original;
+      if (dump_file)
+	fprintf (dump_file,
+		 "Not unifying; "
+		 "adress of original and alias may be compared.\n\n");
+      return false;
+    }
 
-      while (n->alias)
-	{
-	  n = n->get_alias_target ();
-	  if (n == alias)
-	    {
-	      if (dump_file)
-		fprintf (dump_file, "Varpool alias cannot be created (alias cycle).\n\n");
+  if (original_discardable
+      && (!DECL_COMDAT_GROUP (original->decl)
+	  || (DECL_COMDAT_GROUP (original->decl)
+	      != DECL_COMDAT_GROUP (alias->decl))))
+    {
+      if (dump_file)
+	fprintf (dump_file, "Not unifying; alias cannot be created; "
+		 "target is discardable\n\n");
 
-	      return false;
-	    }
-	}
+      return false;
+    }
+  else
+    {
+      gcc_assert (!original->alias);
+      gcc_assert (!alias->alias);
 
       alias->analyzed = false;
 
       DECL_INITIAL (alias->decl) = NULL;
       alias->need_bounds_init = false;
       alias->remove_all_references ();
+      if (TREE_ADDRESSABLE (alias->decl))
+        original->call_for_symbol_thunks_and_aliases
+	 (set_addressable, NULL, true);
 
       varpool_node::create_alias (alias_var->decl, decl);
       alias->resolve_alias (original);
 
       if (dump_file)
-	fprintf (dump_file, "Varpool alias has been created.\n\n");
+	fprintf (dump_file, "Unified; Variable alias has been created.\n\n");
 
       return true;
     }
 }
 
-bool
-sem_variable::compare_sections (sem_variable *alias)
-{
-  const char *source = node->get_section ();
-  const char *target = alias->node->get_section();
-
-  if (source == NULL && target == NULL)
-    return true;
-  else if(!source || !target)
-    return false;
-  else
-    return strcmp (source, target) == 0;
-}
-
 /* Dump symbol to FILE.  */
 
 void
Index: cgraphclones.c
===================================================================
--- cgraphclones.c	(revision 221034)
+++ cgraphclones.c	(working copy)
@@ -471,6 +471,8 @@  cgraph_node::create_clone (tree decl, gc
   new_node->frequency = frequency;
   new_node->tp_first_run = tp_first_run;
   new_node->tm_clone = tm_clone;
+  new_node->icf_merged = icf_merged;
+  new_node->merged = merged;
 
   new_node->clone.tree_map = NULL;
   new_node->clone.args_to_skip = args_to_skip;