On Mon, 17 Feb 2014, Jan Hubicka wrote: > > On Fri, 14 Feb 2014, Jan Hubicka wrote: > > > > > > > This smells bad, since it is given a canonical type that is after the > > > > > structural equivalency merging that ignores BINFOs, so it may be > > > > > completely > > > > > different class with completely different bases than the original. > > > > > Bases are > > > > > structuraly merged, too and may be exchanged for normal fields because > > > > > DECL_ARTIFICIAL (that separate bases and fields) does not seem to be > > > > > part of > > > > > the canonical type definition in LTO. > > > > > > > > Can you elaborate on that DECL_ARTIFICIAL thing? That is, what is > > > > broken > > > > by considering all fields during that merging? > > > > > > To make the code work with LTO, one can not merge > > > struct B {struct A a} > > > struct B: A {} > > > > > > these IMO differ only by DECL_ARTIFICIAL flag on the fields. > > > > "The code" == that BINFO walk? Is that because we walk a completely > > Yes. > > > unrelated BINFO chain? I'd say we should have merged its types > > so that difference shouldn't matter. > > > > Hopefully ;) > > I am trying to make point that will matter. Here is completed testcase above: > > struct A {int a;}; > struct C:A {}; > struct B {struct A a;}; > struct C *p2; > struct B *p1; > int > t() > { > p1->a.a = 2; > return p2->a; > } > > With patch I get: > > Index: lto/lto.c > =================================================================== > --- lto/lto.c (revision 207777) > +++ lto/lto.c (working copy) > @@ -49,6 +49,8 @@ along with GCC; see the file COPYING3. > #include "data-streamer.h" > #include "context.h" > #include "pass_manager.h" > +#include "print-tree.h" > > > /* Number of parallel tasks to run, -1 if we want to use GNU Make jobserver. > */ > @@ -619,6 +621,15 @@ gimple_canonical_type_eq (const void *p1 > { > const_tree t1 = (const_tree) p1; > const_tree t2 = (const_tree) p2; > + if (gimple_canonical_types_compatible_p (CONST_CAST_TREE (t1), > + CONST_CAST_TREE (t2)) > + && TREE_CODE (CONST_CAST_TREE (t1)) == RECORD_TYPE) > + { > + debug_tree (CONST_CAST_TREE (t1)); > + fprintf (stderr, "bases:%i\n", BINFO_BASE_BINFOS (TYPE_BINFO > (t1))->length()); > + debug_tree (CONST_CAST_TREE (t2)); > + fprintf (stderr, "bases:%i\n", BINFO_BASE_BINFOS (TYPE_BINFO > (t2))->length()); > + } > return gimple_canonical_types_compatible_p (CONST_CAST_TREE (t1), > CONST_CAST_TREE (t2)); > } > > <record_type 0x7ffff6c52888 B SI > size <integer_cst 0x7ffff6ae83a0 type <integer_type 0x7ffff6ae5150 > bitsizetype> constant 32> > unit size <integer_cst 0x7ffff6ae83c0 type <integer_type 0x7ffff6ae50a8 > sizetype> constant 4> > align 32 symtab 0 alias set -1 canonical type 0x7ffff6c52888 > fields <field_decl 0x7ffff6adec78 a > type <record_type 0x7ffff6c52738 A SI size <integer_cst > 0x7ffff6ae83a0 32> unit size <integer_cst 0x7ffff6ae83c0 4> > align 32 symtab 0 alias set -1 canonical type 0x7ffff6c52738 > fields <field_decl 0x7ffff6adebe0 a> context <translation_unit_decl > 0x7ffff6af2e60 D.2821> > chain <type_decl 0x7ffff6af2f18 A>> > nonlocal SI file t.C line 3 col 20 size <integer_cst 0x7ffff6ae83a0 > 32> unit size <integer_cst 0x7ffff6ae83c0 4> > align 32 offset_align 128 > offset <integer_cst 0x7ffff6ae8060 constant 0> > bit offset <integer_cst 0x7ffff6ae80e0 constant 0> context > <record_type 0x7ffff6c52888 B> > chain <type_decl 0x7ffff6c55170 B type <record_type 0x7ffff6c52930 B> > nonlocal VOID file t.C line 3 col 10 > align 1 context <record_type 0x7ffff6c52888 B> result > <record_type 0x7ffff6c52888 B>>> context <translation_unit_decl > 0x7ffff6af2e60 D.2821> > pointer_to_this <pointer_type 0x7ffff6c529d8> chain <type_decl > 0x7ffff6c550b8 B>> > bases:0 > <record_type 0x7ffff6c52b28 C SI > size <integer_cst 0x7ffff6ae83a0 type <integer_type 0x7ffff6ae5150 > bitsizetype> constant 32> > unit size <integer_cst 0x7ffff6ae83c0 type <integer_type 0x7ffff6ae50a8 > sizetype> constant 4> > align 32 symtab 0 alias set -1 structural equality > fields <field_decl 0x7ffff6adeda8 D.2831 > type <record_type 0x7ffff6c52738 A SI size <integer_cst > 0x7ffff6ae83a0 32> unit size <integer_cst 0x7ffff6ae83c0 4> > align 32 symtab 0 alias set -1 canonical type 0x7ffff6c52738 > fields <field_decl 0x7ffff6adebe0 a> context <translation_unit_decl > 0x7ffff6af2e60 D.2821> > chain <type_decl 0x7ffff6af2f18 A>> > ignored SI file t.C line 2 col 8 size <integer_cst 0x7ffff6ae83a0 32> > unit size <integer_cst 0x7ffff6ae83c0 4> > align 32 offset_align 128 > offset <integer_cst 0x7ffff6ae8060 constant 0> > bit offset <integer_cst 0x7ffff6ae80e0 constant 0> context > <record_type 0x7ffff6c52a80 C> > chain <type_decl 0x7ffff6c552e0 C type <record_type 0x7ffff6c52b28 C> > nonlocal VOID file t.C line 2 col 12 > align 1 context <record_type 0x7ffff6c52a80 C> result > <record_type 0x7ffff6c52a80 C>>> context <translation_unit_decl > 0x7ffff6af2e60 D.2821> > chain <type_decl 0x7ffff6c55228 C>> > bases:1 > > So we prevail structure B with structure C. One has bases to walk other > doesn't. If that BINFO walk in alias.c (on canonical types) did > something useful, we have a wrong code bug.
Yeah, ok. But we treat those types (B and C) TBAA equivalent because structurally they are the same ;) Luckily C has a "proper" field for its base (proper means that offset and size are correct as well as the type). It indeed has DECL_ARTIFICIAL set and yes, we treat those as "real" fields when doing the structural comparison. More interesting is of course when we can re-use tail-padding in one but not the other (works as expected - not merged). struct A { A (); short x; bool a;}; struct C:A { bool b; }; struct B {struct A a; bool b;}; struct C *p2; struct B *p1; int t() { p1->a.a = 2; return p2->a; } > Yes, zero sized classes are those having no fields (but other stuff, > type decls, bases etc.) Yeah, but TBAA obviously doesn't care about type decls and bases. Richard.