public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* TYPE_BINFO and canonical types at LTO
@ 2014-02-14  0:48 Jan Hubicka
  2014-02-14  8:06 ` Jason Merrill
  2014-02-14  8:42 ` Richard Biener
  0 siblings, 2 replies; 18+ messages in thread
From: Jan Hubicka @ 2014-02-14  0:48 UTC (permalink / raw)
  To: gcc, rguenther, jason

Hi,
I have noticed that record_component_aliases is called during LTO time and it
examines contents of BINFO:
0x5cd7a5 record_component_aliases(tree_node*)
        ../../gcc/alias.c:1005
0x5cd4a9 get_alias_set(tree_node*)
        ../../gcc/alias.c:895
0x5cc67a component_uses_parent_alias_set_from(tree_node const*)
        ../../gcc/alias.c:548
0x5ccc42 reference_alias_ptr_type_1
        ../../gcc/alias.c:660
0x5ccf93 get_alias_set(tree_node*)
        ../../gcc/alias.c:740
0xb823d8 indirect_refs_may_alias_p
        ../../gcc/tree-ssa-alias.c:1125
0xb82d8d refs_may_alias_p_1(ao_ref*, ao_ref*, bool)
        ../../gcc/tree-ssa-alias.c:1279
0xb848df stmt_may_clobber_ref_p_1(gimple_statement_base*, ao_ref*)
        ../../gcc/tree-ssa-alias.c:2013
0xb85d27 walk_non_aliased_vuses(ao_ref*, tree_node*, void* (*)(ao_ref*, tree_node*, unsigned int, void*), void* (*)(ao_ref*, tree_node*, void*), void*)
        ../../gcc/tree-ssa-alias.c:2411
0xc509f3 vn_reference_lookup(tree_node*, tree_node*, vn_lookup_kind, vn_reference_s**)
        ../../gcc/tree-ssa-sccvn.c:2063
0xc52ea4 visit_reference_op_store
        ../../gcc/tree-ssa-sccvn.c:2970
0xc55404 extract_and_process_scc_for_name
        ../../gcc/tree-ssa-sccvn.c:3825

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.

I wonder if that code is needed after all:
    case QUAL_UNION_TYPE:
      /* Recursively record aliases for the base classes, if there are any.  */
      if (TYPE_BINFO (type))
        { 
          int i;
          tree binfo, base_binfo;

          for (binfo = TYPE_BINFO (type), i = 0;
               BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
            record_alias_subset (superset,
                                 get_alias_set (BINFO_TYPE (base_binfo)));
        }
      for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN (field))
        if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field))
          record_alias_subset (superset, get_alias_set (TREE_TYPE (field)));
      break;
all bases are also fields of within the type, so the second loop should notice
all the types seen by first loop if I am correct?
So perhaps the loop can be dropped at first place. 

Honza

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-14  0:48 TYPE_BINFO and canonical types at LTO Jan Hubicka
@ 2014-02-14  8:06 ` Jason Merrill
  2014-02-14  8:42 ` Richard Biener
  1 sibling, 0 replies; 18+ messages in thread
From: Jason Merrill @ 2014-02-14  8:06 UTC (permalink / raw)
  To: Jan Hubicka, gcc, rguenther

On 02/13/2014 04:48 PM, Jan Hubicka wrote:
> all bases are also fields of within the type, so the second loop should notice
> all the types seen by first loop if I am correct?

Yes, except that empty bases don't get fields because they have no data. 
  But since they have no data they aren't interesting to aliasing 
either, so you should be OK just looking at field types.

Jason

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-14  0:48 TYPE_BINFO and canonical types at LTO Jan Hubicka
  2014-02-14  8:06 ` Jason Merrill
@ 2014-02-14  8:42 ` Richard Biener
  2014-02-14 16:52   ` Jan Hubicka
  1 sibling, 1 reply; 18+ messages in thread
From: Richard Biener @ 2014-02-14  8:42 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: gcc, jason

On Fri, 14 Feb 2014, Jan Hubicka wrote:

> Hi,
> I have noticed that record_component_aliases is called during LTO time and it
> examines contents of BINFO:
> 0x5cd7a5 record_component_aliases(tree_node*)
>         ../../gcc/alias.c:1005
> 0x5cd4a9 get_alias_set(tree_node*)
>         ../../gcc/alias.c:895
> 0x5cc67a component_uses_parent_alias_set_from(tree_node const*)
>         ../../gcc/alias.c:548
> 0x5ccc42 reference_alias_ptr_type_1
>         ../../gcc/alias.c:660
> 0x5ccf93 get_alias_set(tree_node*)
>         ../../gcc/alias.c:740
> 0xb823d8 indirect_refs_may_alias_p
>         ../../gcc/tree-ssa-alias.c:1125
> 0xb82d8d refs_may_alias_p_1(ao_ref*, ao_ref*, bool)
>         ../../gcc/tree-ssa-alias.c:1279
> 0xb848df stmt_may_clobber_ref_p_1(gimple_statement_base*, ao_ref*)
>         ../../gcc/tree-ssa-alias.c:2013
> 0xb85d27 walk_non_aliased_vuses(ao_ref*, tree_node*, void* (*)(ao_ref*, tree_node*, unsigned int, void*), void* (*)(ao_ref*, tree_node*, void*), void*)
>         ../../gcc/tree-ssa-alias.c:2411
> 0xc509f3 vn_reference_lookup(tree_node*, tree_node*, vn_lookup_kind, vn_reference_s**)
>         ../../gcc/tree-ssa-sccvn.c:2063
> 0xc52ea4 visit_reference_op_store
>         ../../gcc/tree-ssa-sccvn.c:2970
> 0xc55404 extract_and_process_scc_for_name
>         ../../gcc/tree-ssa-sccvn.c:3825
> 
> 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?

Note that the BINFO walk below only adds extra aliasing - it should
be harmless correctness-wise, no?

> I wonder if that code is needed after all:
>     case QUAL_UNION_TYPE:
>       /* Recursively record aliases for the base classes, if there are any.  */
>       if (TYPE_BINFO (type))
>         { 
>           int i;
>           tree binfo, base_binfo;
> 
>           for (binfo = TYPE_BINFO (type), i = 0;
>                BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
>             record_alias_subset (superset,
>                                  get_alias_set (BINFO_TYPE (base_binfo)));
>         }
>       for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN (field))
>         if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field))
>           record_alias_subset (superset, get_alias_set (TREE_TYPE (field)));
>       break;
> all bases are also fields of within the type, so the second loop should notice
> all the types seen by first loop if I am correct?
> So perhaps the loop can be dropped at first place. 

Yeah, I remember seeing that code and thinking the same multiple times.
Though I also vaguely remember that removing that loop regressed
something.  How is virtual inheritance represented in the fields?

But I'd be happy if this BINFO user would go away ;)

(similar in general for the get_alias_set langhook - with LTO we
only preserve extra alias-set zero answers from that)

Richard.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-14  8:42 ` Richard Biener
@ 2014-02-14 16:52   ` Jan Hubicka
  2014-02-14 23:22     ` Jan Hubicka
  2014-02-15 10:03     ` Richard Biener
  0 siblings, 2 replies; 18+ messages in thread
From: Jan Hubicka @ 2014-02-14 16:52 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jan Hubicka, gcc, jason

> > 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.
> 
> Note that the BINFO walk below only adds extra aliasing - it should
> be harmless correctness-wise, no?

If it is needed for the second case, then it we will produce wrong code with LTO
when we merge first and second case toghetr.  If it is not needed, then we are safe
but we don't really need the loop then.

Having the testcase where the BINFO walk is needed for corectness, I can turn
it into wrong code in LTO by interposing the class by structure.

I am rebuilding firefox with sanity checking that the second loop never adds anything
useful. Lets see.
> 
> > I wonder if that code is needed after all:
> >     case QUAL_UNION_TYPE:
> >       /* Recursively record aliases for the base classes, if there are any.  */
> >       if (TYPE_BINFO (type))
> >         { 
> >           int i;
> >           tree binfo, base_binfo;
> > 
> >           for (binfo = TYPE_BINFO (type), i = 0;
> >                BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
> >             record_alias_subset (superset,
> >                                  get_alias_set (BINFO_TYPE (base_binfo)));
> >         }
> >       for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN (field))
> >         if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field))
> >           record_alias_subset (superset, get_alias_set (TREE_TYPE (field)));
> >       break;
> > all bases are also fields of within the type, so the second loop should notice
> > all the types seen by first loop if I am correct?
> > So perhaps the loop can be dropped at first place. 
> 
> Yeah, I remember seeing that code and thinking the same multiple times.
> Though I also vaguely remember that removing that loop regressed
> something.  How is virtual inheritance represented in the fields?

struct A {int a;};
struct B: virtual A {};
struct C: virtual A {};
struct D: B, C {};
struct D *d;
struct B *b;
int t(void)
{
  d->a=1;
  return b->a;
}

I srepresented as:

 <record_type 0x7ffff6c58000 D addressable needs-constructing type_5 BLK
    size <integer_cst 0x7ffff6ae98c0 type <integer_type 0x7ffff6ae7150 bitsizetype> constant 192>
    unit size <integer_cst 0x7ffff6ae9880 type <integer_type 0x7ffff6ae70a8 sizetype> constant 24>
    align 64 symtab 0 alias set 6 canonical type 0x7ffff6c58000
    fields <field_decl 0x7ffff6c4ae40 D.2249
        type <record_type 0x7ffff6c452a0 B addressable needs-constructing type_5 BLK
            size <integer_cst 0x7ffff6ae9140 constant 128>
            unit size <integer_cst 0x7ffff6ae9160 constant 16>
            align 64 symtab 0 alias set 3 canonical type 0x7ffff6c452a0 fields <field_decl 0x7ffff6c4a2f8 _vptr.B> context <translation_unit_decl 0x7ffff6af1170 D.1>
            full-name "struct B"
            needs-constructor X() X(constX&) this=(X&) n_parents=1 use_template=0 interface-unknown
            pointer_to_this <pointer_type 0x7ffff6c58b28> chain <type_decl 0x7ffff6c3ea10 B>>
        ignored decl_6 BLK file t.C line 4 col 8
        size <integer_cst 0x7ffff6ae90c0 constant 64>
        unit size <integer_cst 0x7ffff6ae90e0 constant 8>
        align 64 offset_align 128
        offset <integer_cst 0x7ffff6ae9100 constant 0>
        bit offset <integer_cst 0x7ffff6ae9180 constant 0> context <record_type 0x7ffff6c58000 D>
        chain <field_decl 0x7ffff6c4aed8 D.2250 type <record_type 0x7ffff6c45b28 C>
            ignored decl_6 BLK file t.C line 4 col 8 size <integer_cst 0x7ffff6ae90c0 64> unit size <integer_cst 0x7ffff6ae90e0 8>
            align 64 offset_align 128 offset <integer_cst 0x7ffff6ae9100 0> bit offset <integer_cst 0x7ffff6ae90c0 64> context <record_type 0x7ffff6c58000 D> chain <type_decl 0x7ffff6c590b8 D>>> context <translation_unit_decl 0x7ffff6af1170 D.1>
    full-name "struct D"
    needs-constructor X() X(constX&) this=(X&) n_parents=2 use_template=0 interface-unknown
    pointer_to_this <pointer_type 0x7ffff6c58a80> chain <type_decl 0x7ffff6c59000 D>>


You my end up with A being a field, too, but that only bypas the recursion.

> 
> But I'd be happy if this BINFO user would go away ;)

Me too, indeed.
> 
> (similar in general for the get_alias_set langhook - with LTO we
> only preserve extra alias-set zero answers from that)

I see, I was surprised we construct alias sets at LTO time, I believed we
always stream them in&out.

Honza
> 
> Richard.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-14 16:52   ` Jan Hubicka
@ 2014-02-14 23:22     ` Jan Hubicka
  2014-02-15 10:10       ` Richard Biener
  2014-02-15 10:03     ` Richard Biener
  1 sibling, 1 reply; 18+ messages in thread
From: Jan Hubicka @ 2014-02-14 23:22 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: Richard Biener, gcc, jason

> > > 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.
> > 
> > Note that the BINFO walk below only adds extra aliasing - it should
> > be harmless correctness-wise, no?
> 
> If it is needed for the second case, then it we will produce wrong code with LTO
> when we merge first and second case toghetr.  If it is not needed, then we are safe
> but we don't really need the loop then.
> 
> Having the testcase where the BINFO walk is needed for corectness, I can turn
> it into wrong code in LTO by interposing the class by structure.
> 
> I am rebuilding firefox with sanity checking that the second loop never adds anything
> useful. Lets see.

The code really seems to be adding only cases of zero sized classes.  I use the
following hack in my tree. I do not know how to discover zero sized class, so I
test of unit size 1, but I think if there was other cases, we would notice
anyway.

The reason why I am looking into is that because I am trying to evaulate how
expensive BINFOs are. I am trying to keep only those that matters for debug info and devirt,
and avoid streaming others.

Honza

Index: alias.c
===================================================================
--- alias.c	(revision 207777)
+++ alias.c	(working copy)
@@ -995,20 +996,40 @@ record_component_aliases (tree type)
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
-      /* Recursively record aliases for the base classes, if there are any.  */
-      if (TYPE_BINFO (type))
-	{
-	  int i;
-	  tree binfo, base_binfo;
-
-	  for (binfo = TYPE_BINFO (type), i = 0;
-	       BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
-	    record_alias_subset (superset,
-				 get_alias_set (BINFO_TYPE (base_binfo)));
-	}
-      for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN (field))
-	if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field))
-	  record_alias_subset (superset, get_alias_set (TREE_TYPE (field)));
+      {
+#ifdef ENABLE_CHECKING
+        bitmap_obstack my_obstack;
+        bitmap_obstack_initialize (&my_obstack); 
+	bitmap added = BITMAP_ALLOC (&my_obstack);
+#endif
+	alias_set_type t;
+	for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN (field))
+	  if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field))
+	    {
+	      t = get_alias_set (TREE_TYPE (field));
+#ifdef ENABLE_CHECKING
+	      bitmap_set_bit (added, t);
+#endif
+	      record_alias_subset (superset, t);
+	    }
+#ifdef ENABLE_CHECKING
+	/* Recursively record aliases for the base classes, if there are any.  */
+	if (!in_lto_p && TYPE_BINFO (type))
+	  {
+	    int i;
+	    tree binfo, base_binfo;
+
+	    for (binfo = TYPE_BINFO (type), i = 0;
+		 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+		if (!bitmap_bit_p (added, get_alias_set (BINFO_TYPE (base_binfo))))
+		{
+		  gcc_assert (integer_onep (TYPE_SIZE_UNIT (BINFO_TYPE (base_binfo))));
+		}
+	  }
+	BITMAP_FREE (added);
+  bitmap_obstack_release (&my_obstack);
+#endif
+      }
       break;
 
     case COMPLEX_TYPE:

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-14 16:52   ` Jan Hubicka
  2014-02-14 23:22     ` Jan Hubicka
@ 2014-02-15 10:03     ` Richard Biener
  2014-02-16 23:55       ` Jan Hubicka
  1 sibling, 1 reply; 18+ messages in thread
From: Richard Biener @ 2014-02-15 10:03 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: gcc, jason

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
unrelated BINFO chain?  I'd say we should have merged its types
so that difference shouldn't matter.

Hopefully ;)

> > 
> > Note that the BINFO walk below only adds extra aliasing - it should
> > be harmless correctness-wise, no?
> 
> If it is needed for the second case, then it we will produce wrong code 
> with LTO when we merge first and second case toghetr.  If it is not 
> needed, then we are safe but we don't really need the loop then.
> 
> Having the testcase where the BINFO walk is needed for corectness, I can turn
> it into wrong code in LTO by interposing the class by structure.
> 
> I am rebuilding firefox with sanity checking that the second loop never adds anything
> useful. Lets see.
> > 
> > > I wonder if that code is needed after all:
> > >     case QUAL_UNION_TYPE:
> > >       /* Recursively record aliases for the base classes, if there are any.  */
> > >       if (TYPE_BINFO (type))
> > >         { 
> > >           int i;
> > >           tree binfo, base_binfo;
> > > 
> > >           for (binfo = TYPE_BINFO (type), i = 0;
> > >                BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
> > >             record_alias_subset (superset,
> > >                                  get_alias_set (BINFO_TYPE (base_binfo)));
> > >         }
> > >       for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN (field))
> > >         if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field))
> > >           record_alias_subset (superset, get_alias_set (TREE_TYPE (field)));
> > >       break;
> > > all bases are also fields of within the type, so the second loop should notice
> > > all the types seen by first loop if I am correct?
> > > So perhaps the loop can be dropped at first place. 
> > 
> > Yeah, I remember seeing that code and thinking the same multiple times.
> > Though I also vaguely remember that removing that loop regressed
> > something.  How is virtual inheritance represented in the fields?
> 
> struct A {int a;};
> struct B: virtual A {};
> struct C: virtual A {};
> struct D: B, C {};
> struct D *d;
> struct B *b;
> int t(void)
> {
>   d->a=1;
>   return b->a;
> }
> 
> I srepresented as:
> 
>  <record_type 0x7ffff6c58000 D addressable needs-constructing type_5 BLK
>     size <integer_cst 0x7ffff6ae98c0 type <integer_type 0x7ffff6ae7150 bitsizetype> constant 192>
>     unit size <integer_cst 0x7ffff6ae9880 type <integer_type 0x7ffff6ae70a8 sizetype> constant 24>
>     align 64 symtab 0 alias set 6 canonical type 0x7ffff6c58000
>     fields <field_decl 0x7ffff6c4ae40 D.2249
>         type <record_type 0x7ffff6c452a0 B addressable needs-constructing type_5 BLK
>             size <integer_cst 0x7ffff6ae9140 constant 128>
>             unit size <integer_cst 0x7ffff6ae9160 constant 16>
>             align 64 symtab 0 alias set 3 canonical type 0x7ffff6c452a0 fields <field_decl 0x7ffff6c4a2f8 _vptr.B> context <translation_unit_decl 0x7ffff6af1170 D.1>
>             full-name "struct B"
>             needs-constructor X() X(constX&) this=(X&) n_parents=1 use_template=0 interface-unknown
>             pointer_to_this <pointer_type 0x7ffff6c58b28> chain <type_decl 0x7ffff6c3ea10 B>>
>         ignored decl_6 BLK file t.C line 4 col 8
>         size <integer_cst 0x7ffff6ae90c0 constant 64>
>         unit size <integer_cst 0x7ffff6ae90e0 constant 8>
>         align 64 offset_align 128
>         offset <integer_cst 0x7ffff6ae9100 constant 0>
>         bit offset <integer_cst 0x7ffff6ae9180 constant 0> context <record_type 0x7ffff6c58000 D>
>         chain <field_decl 0x7ffff6c4aed8 D.2250 type <record_type 0x7ffff6c45b28 C>
>             ignored decl_6 BLK file t.C line 4 col 8 size <integer_cst 0x7ffff6ae90c0 64> unit size <integer_cst 0x7ffff6ae90e0 8>
>             align 64 offset_align 128 offset <integer_cst 0x7ffff6ae9100 0> bit offset <integer_cst 0x7ffff6ae90c0 64> context <record_type 0x7ffff6c58000 D> chain <type_decl 0x7ffff6c590b8 D>>> context <translation_unit_decl 0x7ffff6af1170 D.1>
>     full-name "struct D"
>     needs-constructor X() X(constX&) this=(X&) n_parents=2 use_template=0 interface-unknown
>     pointer_to_this <pointer_type 0x7ffff6c58a80> chain <type_decl 0x7ffff6c59000 D>>
> 
> 
> You my end up with A being a field, too, but that only bypas the recursion.
> 
> > 
> > But I'd be happy if this BINFO user would go away ;)
> 
> Me too, indeed.
> > 
> > (similar in general for the get_alias_set langhook - with LTO we
> > only preserve extra alias-set zero answers from that)
> 
> I see, I was surprised we construct alias sets at LTO time, I believed we
> always stream them in&out.

No, we stream out a flag basically, get_alias_set () == 0.  We don't have
a way to merge the alias set forests.

Richard.

> Honza

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-14 23:22     ` Jan Hubicka
@ 2014-02-15 10:10       ` Richard Biener
  2014-02-20 20:49         ` Jason Merrill
  0 siblings, 1 reply; 18+ messages in thread
From: Richard Biener @ 2014-02-15 10:10 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: gcc, jason

On Sat, 15 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.
> > > 
> > > Note that the BINFO walk below only adds extra aliasing - it should
> > > be harmless correctness-wise, no?
> > 
> > If it is needed for the second case, then it we will produce wrong code with LTO
> > when we merge first and second case toghetr.  If it is not needed, then we are safe
> > but we don't really need the loop then.
> > 
> > Having the testcase where the BINFO walk is needed for corectness, I can turn
> > it into wrong code in LTO by interposing the class by structure.
> > 
> > I am rebuilding firefox with sanity checking that the second loop never adds anything
> > useful. Lets see.
> 
> The code really seems to be adding only cases of zero sized classes.

zero-size as in with no fields?  Then we can't do anything with such
classes and thus we don't need to record component aliases?

I'd say we try dropping this loop when stage1 opens again.

Richard.

>  I use the following hack in my tree. I do not know how to discover zero 
> sized class, so I test of unit size 1, but I think if there was other 
> cases, we would notice anyway.
> 
> The reason why I am looking into is that because I am trying to evaulate 
> how expensive BINFOs are. I am trying to keep only those that matters 
> for debug info and devirt, and avoid streaming others.
> 
> Honza
> 
> Index: alias.c
> ===================================================================
> --- alias.c	(revision 207777)
> +++ alias.c	(working copy)
> @@ -995,20 +996,40 @@ record_component_aliases (tree type)
>      case RECORD_TYPE:
>      case UNION_TYPE:
>      case QUAL_UNION_TYPE:
> -      /* Recursively record aliases for the base classes, if there are any.  */
> -      if (TYPE_BINFO (type))
> -	{
> -	  int i;
> -	  tree binfo, base_binfo;
> -
> -	  for (binfo = TYPE_BINFO (type), i = 0;
> -	       BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
> -	    record_alias_subset (superset,
> -				 get_alias_set (BINFO_TYPE (base_binfo)));
> -	}
> -      for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN (field))
> -	if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field))
> -	  record_alias_subset (superset, get_alias_set (TREE_TYPE (field)));
> +      {
> +#ifdef ENABLE_CHECKING
> +        bitmap_obstack my_obstack;
> +        bitmap_obstack_initialize (&my_obstack); 
> +	bitmap added = BITMAP_ALLOC (&my_obstack);
> +#endif
> +	alias_set_type t;
> +	for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN (field))
> +	  if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field))
> +	    {
> +	      t = get_alias_set (TREE_TYPE (field));
> +#ifdef ENABLE_CHECKING
> +	      bitmap_set_bit (added, t);
> +#endif
> +	      record_alias_subset (superset, t);
> +	    }
> +#ifdef ENABLE_CHECKING
> +	/* Recursively record aliases for the base classes, if there are any.  */
> +	if (!in_lto_p && TYPE_BINFO (type))
> +	  {
> +	    int i;
> +	    tree binfo, base_binfo;
> +
> +	    for (binfo = TYPE_BINFO (type), i = 0;
> +		 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
> +		if (!bitmap_bit_p (added, get_alias_set (BINFO_TYPE (base_binfo))))
> +		{
> +		  gcc_assert (integer_onep (TYPE_SIZE_UNIT (BINFO_TYPE (base_binfo))));
> +		}
> +	  }
> +	BITMAP_FREE (added);
> +  bitmap_obstack_release (&my_obstack);
> +#endif
> +      }
>        break;
>  
>      case COMPLEX_TYPE:

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-15 10:03     ` Richard Biener
@ 2014-02-16 23:55       ` Jan Hubicka
  2014-02-17 11:36         ` Richard Biener
  0 siblings, 1 reply; 18+ messages in thread
From: Jan Hubicka @ 2014-02-16 23:55 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jan Hubicka, gcc, jason

> 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.

Yes, zero sized classes are those having no fields (but other stuff, type decls, bases etc.)

Honza

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-16 23:55       ` Jan Hubicka
@ 2014-02-17 11:36         ` Richard Biener
  2014-02-17 20:55           ` Jan Hubicka
  0 siblings, 1 reply; 18+ messages in thread
From: Richard Biener @ 2014-02-17 11:36 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: gcc, jason

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.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-17 11:36         ` Richard Biener
@ 2014-02-17 20:55           ` Jan Hubicka
  2014-02-18  8:51             ` Richard Biener
  2014-02-20 20:57             ` Jason Merrill
  0 siblings, 2 replies; 18+ messages in thread
From: Jan Hubicka @ 2014-02-17 20:55 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jan Hubicka, gcc, jason

> 
> 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.

Yep, the difference is that depending if C or D win, we will end up walking the
BINFO or not.  So we should not depend on the BINFo walk for correctness.
> 
> More interesting is of course when we can re-use tail-padding in
> one but not the other (works as expected - not merged).

Yep.
> 
> 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.

So I guess the conclussion is that the BINFO walk in alias.c is pointless?

Concerning the merging details and LTO aliasing, I think for 4.10 we should
make C++ to compute mangled names of types (i.e. call DECL_ASSEMBLER_NAME on
the associated type_decl + explicitly mark that type is driven by ODR) and then
we can do merging driven by ODR rule.

Non-ODR types born from other frontends will then need to be made to alias all
the ODR variants that can be done by storing them into the current canonical type hash.
(I wonder if we want to support cross language aliasing for non-POD?)

I also think we want explicit representation of types known to be local to compilation
unit - anonymous namespaces in C/C++, types defined within function bodies in C and
god knows what in Ada/Fortran/Java.

Honza
> 
> Richard.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-17 20:55           ` Jan Hubicka
@ 2014-02-18  8:51             ` Richard Biener
  2014-02-18 10:42               ` Richard Biener
  2014-02-18 19:02               ` Jan Hubicka
  2014-02-20 20:57             ` Jason Merrill
  1 sibling, 2 replies; 18+ messages in thread
From: Richard Biener @ 2014-02-18  8:51 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: gcc, jason

On Mon, 17 Feb 2014, Jan Hubicka wrote:

> > 
> > 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.
> 
> Yep, the difference is that depending if C or D win, we will end up walking the
> BINFO or not.  So we should not depend on the BINFo walk for correctness.
> > 
> > More interesting is of course when we can re-use tail-padding in
> > one but not the other (works as expected - not merged).
> 
> Yep.
> > 
> > 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.
> 
> So I guess the conclussion is that the BINFO walk in alias.c is pointless?

Yes.  But as I said - I remember being there and proposing to remove
it.  Some N > 5 years ago or so and it was either rejected or it didn't
work out ;)

> Concerning the merging details and LTO aliasing, I think for 4.10 we 
> should make C++ to compute mangled names of types (i.e. call 
> DECL_ASSEMBLER_NAME on the associated type_decl + explicitly mark that 
> type is driven by ODR) and then we can do merging driven by ODR rule.
> 
> Non-ODR types born from other frontends will then need to be made to 
> alias all the ODR variants that can be done by storing them into the 
> current canonical type hash.
> (I wonder if we want to support cross language aliasing for non-POD?)

Surely for accessing components of non-POD types, no?  Like

class Foo {
Foo();
int *get_data ();
int *data;
} glob_foo;

extern "C" int *get_foo_data() { return glob_foo.get_data(); }

?  But you are talking about the "tree" merging part using ODR info
to also merge types which differ in completeness of contained
pointer types, right?  (exactly equal cases should be already merged)

The canonical type computation happens separately (only for prevailing
types, of course), and there we already "merge" types which differ
in completeness.  Canonical type merging is conservative the other
way aroud - if we merge _all_ types to a single canonical type then
TBAA is still correct (we get a single alias set).

> I also think we want explicit representation of types known to be local 
> to compilation unit - anonymous namespaces in C/C++, types defined 
> within function bodies in C and god knows what in Ada/Fortran/Java.

But here you get into the idea of improving TBAA, thus having
_more_ distinct canonical types?

Just to make sure to not mix those two ;)

And whatever "frontend knowledge" we want to excercise - please
make sure we get a reliable way for the middle-end to see
that "frontend knowledge" (no langhooks!).  Thus, make it
"middle-end knowledge".

Oh - and the easiest way to improve things is to get less types into
the merging process in the first place!

Richard.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-18  8:51             ` Richard Biener
@ 2014-02-18 10:42               ` Richard Biener
  2014-02-18 19:02               ` Jan Hubicka
  1 sibling, 0 replies; 18+ messages in thread
From: Richard Biener @ 2014-02-18 10:42 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: gcc, jason

On Tue, 18 Feb 2014, Richard Biener wrote:

> On Mon, 17 Feb 2014, Jan Hubicka wrote:
> 
> > > 
> > > 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.
> > 
> > Yep, the difference is that depending if C or D win, we will end up walking the
> > BINFO or not.  So we should not depend on the BINFo walk for correctness.
> > > 
> > > More interesting is of course when we can re-use tail-padding in
> > > one but not the other (works as expected - not merged).
> > 
> > Yep.
> > > 
> > > 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.
> > 
> > So I guess the conclussion is that the BINFO walk in alias.c is pointless?
> 
> Yes.  But as I said - I remember being there and proposing to remove
> it.  Some N > 5 years ago or so and it was either rejected or it didn't
> work out ;)

Btw, a bootstrap & regtest worked fine with removing that loop
(not that this proves anything).

Richard.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-18  8:51             ` Richard Biener
  2014-02-18 10:42               ` Richard Biener
@ 2014-02-18 19:02               ` Jan Hubicka
  2014-02-19 12:16                 ` Richard Biener
  1 sibling, 1 reply; 18+ messages in thread
From: Jan Hubicka @ 2014-02-18 19:02 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jan Hubicka, gcc, jason

> > Non-ODR types born from other frontends will then need to be made to 
> > alias all the ODR variants that can be done by storing them into the 
> > current canonical type hash.
> > (I wonder if we want to support cross language aliasing for non-POD?)
> 
> Surely for accessing components of non-POD types, no?  Like
> 
> class Foo {
> Foo();
> int *get_data ();
> int *data;
> } glob_foo;
> 
> extern "C" int *get_foo_data() { return glob_foo.get_data(); }

OK, if we want to support this, then we want to merge.
What about types with vtbl pointer? :)
> 
> ?  But you are talking about the "tree" merging part using ODR info
> to also merge types which differ in completeness of contained
> pointer types, right?  (exactly equal cases should be already merged)

Actually I was speaking of canonical types here. I want to preserve more of TBAA
via honoring ODR and local types.
I want to change lto to not merge canonical types for pairs of types of same layout
(i.e. equivalent in the current canonical type definition) but with different
mangled names. I also want it to never merge when types are local.
For inter-language TBAA we will need to ensure aliasing in between non-ODR type
of same layout and all unmerged variants of ODR type.  Can it be done by attaching
chains of ODR types into the canonical type hash and when non-ODR type appears, just
make it alias with all of them?

It would make sense to ODR merge in tree merging, too, but I am not sure if
this fits the current design, since you would need to merge SCC components of
different shape then that seems hard, right?

It may be easier to ODR merge after streaming (during DECL fixup) just to make
WPA streaming cheaper and to reduce debug info size.  If you use
-fdump-ipa-devirt, it will dump you ODR types that did not get merged (only
ones with vtable pointers in them ATM) and there are quite long chains for
firefox. Surely then hundreds of duplicated ODR types will end up in the ltrans
partition streams and they eventually hit debug output machinery.
Eric sent me presentation about doing this in LLVM.
http://llvm.org/devmtg/2013-11/slides/Christopher-DebugInfo.pdf
> 
> The canonical type computation happens separately (only for prevailing
> types, of course), and there we already "merge" types which differ
> in completeness.  Canonical type merging is conservative the other
> way aroud - if we merge _all_ types to a single canonical type then
> TBAA is still correct (we get a single alias set).

Yes, I think I understand that. One equivalence is kind of minimal so we merge
only if we are sure there is no informationloss, other is maximal so we are
sure that types that needs to be equivalent by whatever underlying langauge
TBAA rules are actually equivalent.
> 
> > I also think we want explicit representation of types known to be local 
> > to compilation unit - anonymous namespaces in C/C++, types defined 
> > within function bodies in C and god knows what in Ada/Fortran/Java.
> 
> But here you get into the idea of improving TBAA, thus having
> _more_ distinct canonical types?

Yes.
> 
> Just to make sure to not mix those two ;)
> 
> And whatever "frontend knowledge" we want to excercise - please
> make sure we get a reliable way for the middle-end to see
> that "frontend knowledge" (no langhooks!).  Thus, make it
> "middle-end knowledge".

Sure that is what I am proposing - just have DECL_ASSEMBLER_NAME on TYPE_DECL
and ODR flag. Middle-end when comparing types will test ODR flag and if flag
is set, then it will compare via DECL_ASEBMLER_NAME (TYPE_DECL (type)).
No langhooks needed here + if other language has similar inter-unit equivalency
it can use the same mechanizm. Just turn the equivalency description into
string identifiers.
> 
> Oh - and the easiest way to improve things is to get less types into
> the merging process in the first place!

Yep, my experiments with not streaming BINFO are directed in it.  I will collect
some numbers and send.

Honza
> 
> Richard.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-18 19:02               ` Jan Hubicka
@ 2014-02-19 12:16                 ` Richard Biener
  2014-02-19 19:19                   ` Jan Hubicka
  0 siblings, 1 reply; 18+ messages in thread
From: Richard Biener @ 2014-02-19 12:16 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: gcc, jason

On Tue, 18 Feb 2014, Jan Hubicka wrote:

> > > Non-ODR types born from other frontends will then need to be made to 
> > > alias all the ODR variants that can be done by storing them into the 
> > > current canonical type hash.
> > > (I wonder if we want to support cross language aliasing for non-POD?)
> > 
> > Surely for accessing components of non-POD types, no?  Like
> > 
> > class Foo {
> > Foo();
> > int *get_data ();
> > int *data;
> > } glob_foo;
> > 
> > extern "C" int *get_foo_data() { return glob_foo.get_data(); }
> 
> OK, if we want to support this, then we want to merge.
> What about types with vtbl pointer? :)

I can easily create a C struct variant covering that.  Basically
in _practice_ I can inter-operate with any language from C if I
know its ABI.  Do we really want to make this undefined?  See
the (even standard) Fortran - C interoperability spec.  I'm sure
something exists for Ada interoperating with C (or even C++).

> > ?  But you are talking about the "tree" merging part using ODR info
> > to also merge types which differ in completeness of contained
> > pointer types, right?  (exactly equal cases should be already merged)
> 
> Actually I was speaking of canonical types here. I want to preserve more 
> of TBAA via honoring ODR and local types.

So, are you positive there will be a net gain in optimization when
doing that?  Please factor in the surprises you'll get when code
gets "miscompiled" because of "slight" ODR violations or interoperability
that no longer works.

> I want to change lto to not 
> merge canonical types for pairs of types of same layout (i.e. equivalent 
> in the current canonical type definition) but with different mangled 
> names.

Names are nothing ;)  In C I very often see different _names_ used
in headers vs. implementation (when the implementation uses a different
internal header).  You have struct Foo; in public headers vs.
struct Foo_impl; in the implementation.

> I also want it to never merge when types are local. For 
> inter-language TBAA we will need to ensure aliasing in between non-ODR 
> type of same layout and all unmerged variants of ODR type.
>  Can it be 
> done by attaching chains of ODR types into the canonical type hash and 
> when non-ODR type appears, just make it alias with all of them?

No, how would that work?

> It would make sense to ODR merge in tree merging, too, but I am not sure if
> this fits the current design, since you would need to merge SCC components of
> different shape then that seems hard, right?

Right.  You'd lose the nice incremental SCC merging (where we haven't even
yet implemented the nicest way - avoid re-materializing the SCC until
we know it prevails).

> It may be easier to ODR merge after streaming (during DECL fixup) just to make
> WPA streaming cheaper and to reduce debug info size.  If you use
> -fdump-ipa-devirt, it will dump you ODR types that did not get merged (only
> ones with vtable pointers in them ATM) and there are quite long chains for
> firefox. Surely then hundreds of duplicated ODR types will end up in the ltrans
> partition streams and they eventually hit debug output machinery.
> Eric sent me presentation about doing this in LLVM.
> http://llvm.org/devmtg/2013-11/slides/Christopher-DebugInfo.pdf

Debuginfo is sth completely separate and should be done separately
(early debug), avoiding to stream the types in the first place.

> > 
> > The canonical type computation happens separately (only for prevailing
> > types, of course), and there we already "merge" types which differ
> > in completeness.  Canonical type merging is conservative the other
> > way aroud - if we merge _all_ types to a single canonical type then
> > TBAA is still correct (we get a single alias set).
> 
> Yes, I think I understand that. One equivalence is kind of minimal so we merge
> only if we are sure there is no informationloss, other is maximal so we are
> sure that types that needs to be equivalent by whatever underlying langauge
> TBAA rules are actually equivalent.

The former is just not correct - it would mean that not merging at all
would be valid, which it is not (you'd create wrong-code all over the 
place).

We still don't merge enough (because of latent bugs that I didn't manage
to fix in time) - thus we do not merge all structurally equivalent types
right now.

> > > I also think we want explicit representation of types known to be local 
> > > to compilation unit - anonymous namespaces in C/C++, types defined 
> > > within function bodies in C and god knows what in Ada/Fortran/Java.
> > 
> > But here you get into the idea of improving TBAA, thus having
> > _more_ distinct canonical types?
> 
> Yes.
> > 
> > Just to make sure to not mix those two ;)
> > 
> > And whatever "frontend knowledge" we want to excercise - please
> > make sure we get a reliable way for the middle-end to see
> > that "frontend knowledge" (no langhooks!).  Thus, make it
> > "middle-end knowledge".
> 
> Sure that is what I am proposing - just have DECL_ASSEMBLER_NAME on TYPE_DECL
> and ODR flag. Middle-end when comparing types will test ODR flag and if flag
> is set, then it will compare via DECL_ASEBMLER_NAME (TYPE_DECL (type)).
> No langhooks needed here + if other language has similar inter-unit equivalency
> it can use the same mechanizm. Just turn the equivalency description into
> string identifiers.

Ok.  You have to be aware of the effects on inter-language 
interoperability though (you'll break it).  Thus I'd make this
guarded by -fextra-strict-aliasing and only auto-enable that when
all TUs are produced by the same frontend (easy enough to check I guess).

Richard.

> > Oh - and the easiest way to improve things is to get less types into
> > the merging process in the first place!
> 
> Yep, my experiments with not streaming BINFO are directed in it.  I will collect
> some numbers and send.
> 
> Honza
> > 
> > Richard.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-19 12:16                 ` Richard Biener
@ 2014-02-19 19:19                   ` Jan Hubicka
  2014-02-20 11:28                     ` Richard Biener
  0 siblings, 1 reply; 18+ messages in thread
From: Jan Hubicka @ 2014-02-19 19:19 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jan Hubicka, gcc, jason

> On Tue, 18 Feb 2014, Jan Hubicka wrote:
> 
> > > > Non-ODR types born from other frontends will then need to be made to 
> > > > alias all the ODR variants that can be done by storing them into the 
> > > > current canonical type hash.
> > > > (I wonder if we want to support cross language aliasing for non-POD?)
> > > 
> > > Surely for accessing components of non-POD types, no?  Like
> > > 
> > > class Foo {
> > > Foo();
> > > int *get_data ();
> > > int *data;
> > > } glob_foo;
> > > 
> > > extern "C" int *get_foo_data() { return glob_foo.get_data(); }
> > 
> > OK, if we want to support this, then we want to merge.
> > What about types with vtbl pointer? :)
> 
> I can easily create a C struct variant covering that.  Basically
> in _practice_ I can inter-operate with any language from C if I
> know its ABI.  Do we really want to make this undefined?  See
> the (even standard) Fortran - C interoperability spec.  I'm sure
> something exists for Ada interoperating with C (or even C++).

Well, if you know the ABI, you can interoperate C
struct {int a,b;};
with
struct {struct {int a;} a; struct {int b;}};

So we don't interoperate everything.  We may eventually want to define what
kind of inter-operation we support.  non-POD class layout is not always a
natural extension of C struct layout as one would expect
http://mentorembedded.github.io/cxx-abi/abi.html#layout
so it may make sense to declare it uninteroperable if it helps something in real
world (which I am not quite sure about)

I am not really shooting for this. I just want to get something that would
improve TBAA in pre-dominantly C++ programs (with some C code in them) such as
firefox, chromium, openoffice or GCC. Because I see us giving up on TBAA very
often when playing with cases that should be devirtualized by GVN/aggregate
propagation in ipa-prop but aren't. Also given that C++ standard actually
have notion of inter-module type equivalence it may be good idea to honnor it.
> 
> > > ?  But you are talking about the "tree" merging part using ODR info
> > > to also merge types which differ in completeness of contained
> > > pointer types, right?  (exactly equal cases should be already merged)
> > 
> > Actually I was speaking of canonical types here. I want to preserve more 
> > of TBAA via honoring ODR and local types.
> 
> So, are you positive there will be a net gain in optimization when
> doing that?  Please factor in the surprises you'll get when code
> gets "miscompiled" because of "slight" ODR violations or interoperability
> that no longer works.
> 
> > I want to change lto to not 
> > merge canonical types for pairs of types of same layout (i.e. equivalent 
> > in the current canonical type definition) but with different mangled 
> > names.
> 
> Names are nothing ;)  In C I very often see different _names_ used
> in headers vs. implementation (when the implementation uses a different
> internal header).  You have struct Foo; in public headers vs.
> struct Foo_impl; in the implementation.

Yes, I am aware of that - I had to go through all those issues with --combine
code in mid 2000s. C++ is different.
What I want is to make TBAA in between C++ types stronger and TBAA between
C++ and other languages to do pretty much what we donot, if possible.
> 
> > I also want it to never merge when types are local. For 
> > inter-language TBAA we will need to ensure aliasing in between non-ODR 
> > type of same layout and all unmerged variants of ODR type.
> >  Can it be 
> > done by attaching chains of ODR types into the canonical type hash and 
> > when non-ODR type appears, just make it alias with all of them?
> 
> No, how would that work?

This is what I am asking you about.
At the end of streaming process, we will have canonical type hash with one leader
and list of ODR variants that was not merged based on ODR rules.
If leader happens to be non-ODR, then it must be made to alias all of them.
I think either we can rewrite all ODR cases to have the non-ODR as canonical type
or make something more fine grained so we can force loads/stores through non-ODR
types to alias with all of them, but loads/stores through ODR types to alias
as within C++ compilation unit.
> 
> > It would make sense to ODR merge in tree merging, too, but I am not sure if
> > this fits the current design, since you would need to merge SCC components of
> > different shape then that seems hard, right?
> 
> Right.  You'd lose the nice incremental SCC merging (where we haven't even
> yet implemented the nicest way - avoid re-materializing the SCC until
> we know it prevails).

Yes, SCC merging w/o re-materialization is a priority, indeed.
> 
> > It may be easier to ODR merge after streaming (during DECL fixup) just to make
> > WPA streaming cheaper and to reduce debug info size.  If you use
> > -fdump-ipa-devirt, it will dump you ODR types that did not get merged (only
> > ones with vtable pointers in them ATM) and there are quite long chains for
> > firefox. Surely then hundreds of duplicated ODR types will end up in the ltrans
> > partition streams and they eventually hit debug output machinery.
> > Eric sent me presentation about doing this in LLVM.
> > http://llvm.org/devmtg/2013-11/slides/Christopher-DebugInfo.pdf
> 
> Debuginfo is sth completely separate and should be done separately
> (early debug), avoiding to stream the types in the first place.

If we generate dwarf dies, we still need to hook them to our IL so we know what they describe.
We will also need to merge them. LLVM basically does early debug and it does the merging
and it needs 13GB extra memory use when you compile firefox with -g compared to no -g.
So it seems to serve as a warning that this path is not 100% problem-free either.

But yes, it is a separate issue.
> 
> > > 
> > > The canonical type computation happens separately (only for prevailing
> > > types, of course), and there we already "merge" types which differ
> > > in completeness.  Canonical type merging is conservative the other
> > > way aroud - if we merge _all_ types to a single canonical type then
> > > TBAA is still correct (we get a single alias set).
> > 
> > Yes, I think I understand that. One equivalence is kind of minimal so we merge
> > only if we are sure there is no informationloss, other is maximal so we are
> > sure that types that needs to be equivalent by whatever underlying langauge
> > TBAA rules are actually equivalent.
> 
> The former is just not correct - it would mean that not merging at all
> would be valid, which it is not (you'd create wrong-code all over the 
> place).

Ah yes, because of memory layout differences.
> 
> Ok.  You have to be aware of the effects on inter-language 
> interoperability though (you'll break it).  Thus I'd make this
> guarded by -fextra-strict-aliasing and only auto-enable that when
> all TUs are produced by the same frontend (easy enough to check I guess).

What I am trying to propose (in first step) should be safe inter-language.
But yes, we can start doing it optional and gain some experience. I am sure
there will be surprises ;)

Honza
> 
> Richard.
> 
> > > Oh - and the easiest way to improve things is to get less types into
> > > the merging process in the first place!
> > 
> > Yep, my experiments with not streaming BINFO are directed in it.  I will collect
> > some numbers and send.
> > 
> > Honza
> > > 
> > > Richard.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-19 19:19                   ` Jan Hubicka
@ 2014-02-20 11:28                     ` Richard Biener
  0 siblings, 0 replies; 18+ messages in thread
From: Richard Biener @ 2014-02-20 11:28 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: gcc, jason

On Wed, 19 Feb 2014, Jan Hubicka wrote:

> > On Tue, 18 Feb 2014, Jan Hubicka wrote:
> > 
> > > > > Non-ODR types born from other frontends will then need to be made to 
> > > > > alias all the ODR variants that can be done by storing them into the 
> > > > > current canonical type hash.
> > > > > (I wonder if we want to support cross language aliasing for non-POD?)
> > > > 
> > > > Surely for accessing components of non-POD types, no?  Like
> > > > 
> > > > class Foo {
> > > > Foo();
> > > > int *get_data ();
> > > > int *data;
> > > > } glob_foo;
> > > > 
> > > > extern "C" int *get_foo_data() { return glob_foo.get_data(); }
> > > 
> > > OK, if we want to support this, then we want to merge.
> > > What about types with vtbl pointer? :)
> > 
> > I can easily create a C struct variant covering that.  Basically
> > in _practice_ I can inter-operate with any language from C if I
> > know its ABI.  Do we really want to make this undefined?  See
> > the (even standard) Fortran - C interoperability spec.  I'm sure
> > something exists for Ada interoperating with C (or even C++).
> 
> Well, if you know the ABI, you can interoperate C
> struct {int a,b;};
> with
> struct {struct {int a;} a; struct {int b;}};
> 
> So we don't interoperate everything.  We may eventually want to define what
> kind of inter-operation we support.  non-POD class layout is not always a
> natural extension of C struct layout as one would expect
> http://mentorembedded.github.io/cxx-abi/abi.html#layout
> so it may make sense to declare it uninteroperable if it helps something in real
> world (which I am not quite sure about)

I'm considering interoperation as defined by language standards
(definitely existing for Fortran <-> C) only.  I'm quite sure such
language specified interoperation exists for Ada as well and it
does exist for Java NI / C++ (not that we care here I guess).

I'm not at all sure to what extent interoperation between C and C++
is defined (apart from knowing 'extern "C"' to avoid mangling), so
I'm curious there.

So what we need to make sure is that the TBAA we apply does not break
when LTO-ing "valid" cross-language interoperation.  The current 
implementation is somewhat ad-hoc and tries to be very conservative
(but at the same time has known issues).

> I am not really shooting for this. I just want to get something that would
> improve TBAA in pre-dominantly C++ programs (with some C code in them) such as
> firefox, chromium, openoffice or GCC. Because I see us giving up on TBAA very
> often when playing with cases that should be devirtualized by GVN/aggregate
> propagation in ipa-prop but aren't. Also given that C++ standard actually
> have notion of inter-module type equivalence it may be good idea to honnor it.

Sure.  You can also track "language" per function and update it to
"mix" when inlining different language functions (but then you have to
implement knowledge into IPA propagators as well), and then fall back
to conservative TBAA for functions with cross-language interoperation.

I'm just not sure how to represent those "two" views of TBAA with
current infrastructure ...

> > 
> > > > ?  But you are talking about the "tree" merging part using ODR info
> > > > to also merge types which differ in completeness of contained
> > > > pointer types, right?  (exactly equal cases should be already merged)
> > > 
> > > Actually I was speaking of canonical types here. I want to preserve more 
> > > of TBAA via honoring ODR and local types.
> > 
> > So, are you positive there will be a net gain in optimization when
> > doing that?  Please factor in the surprises you'll get when code
> > gets "miscompiled" because of "slight" ODR violations or interoperability
> > that no longer works.
> > 
> > > I want to change lto to not 
> > > merge canonical types for pairs of types of same layout (i.e. equivalent 
> > > in the current canonical type definition) but with different mangled 
> > > names.
> > 
> > Names are nothing ;)  In C I very often see different _names_ used
> > in headers vs. implementation (when the implementation uses a different
> > internal header).  You have struct Foo; in public headers vs.
> > struct Foo_impl; in the implementation.
> 
> Yes, I am aware of that - I had to go through all those issues with --combine
> code in mid 2000s. C++ is different.
> What I want is to make TBAA in between C++ types stronger and TBAA between
> C++ and other languages to do pretty much what we donot, if possible.
> > 
> > > I also want it to never merge when types are local. For 
> > > inter-language TBAA we will need to ensure aliasing in between non-ODR 
> > > type of same layout and all unmerged variants of ODR type.
> > >  Can it be 
> > > done by attaching chains of ODR types into the canonical type hash and 
> > > when non-ODR type appears, just make it alias with all of them?
> > 
> > No, how would that work?
> 
> This is what I am asking you about. At the end of streaming process, we 
> will have canonical type hash with one leader and list of ODR variants 
> that was not merged based on ODR rules. If leader happens to be non-ODR, 
> then it must be made to alias all of them. I think either we can rewrite 
> all ODR cases to have the non-ODR as canonical type or make something 
> more fine grained so we can force loads/stores through non-ODR types to 
> alias with all of them, but loads/stores through ODR types to alias as 
> within C++ compilation unit.

Ok, so currently we don't have that "list of variants" but we could
keep it.  So we'd compute the conservative TYPE_CANONICAL but keep
a list of "equivalent" types during streaming.

After streaming we iterate over all canonical type leaders, looking
in the list of structurally equal types and if all of them need
to follow ODR rules split this canonical group into multiple distinct
groups based on ODR rules?

We can (and should) do that at LTRANS stage only?  That avoids
the need to keep the list at WPA time and the time to dissect the
groups?

> > > It would make sense to ODR merge in tree merging, too, but I am not sure if
> > > this fits the current design, since you would need to merge SCC components of
> > > different shape then that seems hard, right?
> > 
> > Right.  You'd lose the nice incremental SCC merging (where we haven't even
> > yet implemented the nicest way - avoid re-materializing the SCC until
> > we know it prevails).
> 
> Yes, SCC merging w/o re-materialization is a priority, indeed.

Yeah.  It should be quite easy to do for SCCs without hash collisions
(just keep around the on-disk SCC rep of the prevailing SCC and
do a memcmp with the SCC you are about to read).  For SCCs with
hash collisions the compare isn't so trivial so maybe we'd just keep
the re-materializing code-path for those.  We can easily stream
a flag whether the SCC does have multiple entries with the same hash
or not.

I will probably play with this during next stage1 if nobody beats me
on it (you can add statistics to lto-streamer-out.c:1254 to see
how many SCCs or SCC entries you'll cover with that approach).

Richard.

> > > It may be easier to ODR merge after streaming (during DECL fixup) just to make
> > > WPA streaming cheaper and to reduce debug info size.  If you use
> > > -fdump-ipa-devirt, it will dump you ODR types that did not get merged (only
> > > ones with vtable pointers in them ATM) and there are quite long chains for
> > > firefox. Surely then hundreds of duplicated ODR types will end up in the ltrans
> > > partition streams and they eventually hit debug output machinery.
> > > Eric sent me presentation about doing this in LLVM.
> > > http://llvm.org/devmtg/2013-11/slides/Christopher-DebugInfo.pdf
> > 
> > Debuginfo is sth completely separate and should be done separately
> > (early debug), avoiding to stream the types in the first place.
> 
> If we generate dwarf dies, we still need to hook them to our IL so we know what they describe.
> We will also need to merge them. LLVM basically does early debug and it does the merging
> and it needs 13GB extra memory use when you compile firefox with -g compared to no -g.
> So it seems to serve as a warning that this path is not 100% problem-free either.
> 
> But yes, it is a separate issue.
> > 
> > > > 
> > > > The canonical type computation happens separately (only for prevailing
> > > > types, of course), and there we already "merge" types which differ
> > > > in completeness.  Canonical type merging is conservative the other
> > > > way aroud - if we merge _all_ types to a single canonical type then
> > > > TBAA is still correct (we get a single alias set).
> > > 
> > > Yes, I think I understand that. One equivalence is kind of minimal so we merge
> > > only if we are sure there is no informationloss, other is maximal so we are
> > > sure that types that needs to be equivalent by whatever underlying langauge
> > > TBAA rules are actually equivalent.
> > 
> > The former is just not correct - it would mean that not merging at all
> > would be valid, which it is not (you'd create wrong-code all over the 
> > place).
> 
> Ah yes, because of memory layout differences.
> > 
> > Ok.  You have to be aware of the effects on inter-language 
> > interoperability though (you'll break it).  Thus I'd make this
> > guarded by -fextra-strict-aliasing and only auto-enable that when
> > all TUs are produced by the same frontend (easy enough to check I guess).
> 
> What I am trying to propose (in first step) should be safe inter-language.
> But yes, we can start doing it optional and gain some experience. I am sure
> there will be surprises ;)
> 
> Honza
> > 
> > Richard.
> > 
> > > > Oh - and the easiest way to improve things is to get less types into
> > > > the merging process in the first place!
> > > 
> > > Yep, my experiments with not streaming BINFO are directed in it.  I will collect
> > > some numbers and send.
> > > 
> > > Honza
> > > > 
> > > > Richard.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-15 10:10       ` Richard Biener
@ 2014-02-20 20:49         ` Jason Merrill
  0 siblings, 0 replies; 18+ messages in thread
From: Jason Merrill @ 2014-02-20 20:49 UTC (permalink / raw)
  To: Richard Biener, Jan Hubicka; +Cc: gcc

On 02/15/2014 05:09 AM, Richard Biener wrote:
> On Sat, 15 Feb 2014, Jan Hubicka wrote:
>> The code really seems to be adding only cases of zero sized classes.
>
> zero-size as in with no fields?  Then we can't do anything with such
> classes and thus we don't need to record component aliases?

Right.  The TYPE_SIZE of an empty class is still 1, but a base of such a 
type doesn't get a FIELD_DECL.

Jason

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: TYPE_BINFO and canonical types at LTO
  2014-02-17 20:55           ` Jan Hubicka
  2014-02-18  8:51             ` Richard Biener
@ 2014-02-20 20:57             ` Jason Merrill
  1 sibling, 0 replies; 18+ messages in thread
From: Jason Merrill @ 2014-02-20 20:57 UTC (permalink / raw)
  To: Jan Hubicka, Richard Biener; +Cc: gcc

On 02/17/2014 03:55 PM, Jan Hubicka wrote:
> I also think we want explicit representation of types known to be local to compilation
> unit - anonymous namespaces in C/C++, types defined within function bodies in C and
> god knows what in Ada/Fortran/Java.

In the C++ front end we set TREE_PUBLIC appropriately on the TYPE_DECL 
of a named type.

Jason

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2014-02-20 20:57 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-14  0:48 TYPE_BINFO and canonical types at LTO Jan Hubicka
2014-02-14  8:06 ` Jason Merrill
2014-02-14  8:42 ` Richard Biener
2014-02-14 16:52   ` Jan Hubicka
2014-02-14 23:22     ` Jan Hubicka
2014-02-15 10:10       ` Richard Biener
2014-02-20 20:49         ` Jason Merrill
2014-02-15 10:03     ` Richard Biener
2014-02-16 23:55       ` Jan Hubicka
2014-02-17 11:36         ` Richard Biener
2014-02-17 20:55           ` Jan Hubicka
2014-02-18  8:51             ` Richard Biener
2014-02-18 10:42               ` Richard Biener
2014-02-18 19:02               ` Jan Hubicka
2014-02-19 12:16                 ` Richard Biener
2014-02-19 19:19                   ` Jan Hubicka
2014-02-20 11:28                     ` Richard Biener
2014-02-20 20:57             ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).