Hi,
Jason, this is about C++ frontend producing two copies of same type with
different TYPE_CANONICAL but same get_alias_set.  Since the types are
structurally different, this does not go well with LTO which no longer
sees they are same.  They are created in
  if (CLASSTYPE_NON_LAYOUT_POD_P (t) || CLASSTYPE_EMPTY_P (t))
      {
       /* T needs a different layout as a base (eliding virtual bases
          or whatever).  Create that version.  */
       tree base_t = make_node (TREE_CODE (t));

and later cxx_get_alias_set arranges they have same set by testing
IS_FAKE_BASE_TYPE.


I am not able to come with a testcase that triggers wrong code with LTO
However compiling this testcase:

struct E {
  ~E();
  virtual void f() const;
};
struct B : E {};
struct G : virtual B {};
struct A {
  virtual ~A();
};
struct J : E {
  int val;
  ~J() {if (val) __builtin_abort ();}
  void f() const {
    E *p = 0;
    p->f();
  }
};
J h;
struct I : A, G, virtual B {};

Front-end produce two versions of J that do not pass
gimple_canonical_types_compatible_p thus at compile time they have same
alias set and at LTO time they are considered non-conflicting.

Both types are mixed in one function:

J::~J (struct J * const this)
{
  int _1;
  struct E * _2;

  <bb 2> [local count: 1073741824]:
  this_4(D)->D.2376._vptr.E = &MEM <int (*__vtbl_ptr_type) ()[3]> [(void 
*)&_ZTV1J + 16B];
  _1 = this_4(D)->val;
  if (_1 != 0)
    goto <bb 3>; [0.00%]
  else
    goto <bb 4>; [100.00%]

  <bb 3> [count: 0]:
  abort ();

  <bb 4> [local count: 1073741824]:
  _2 = &this_4(D)->D.2376;
  E::~E (_2);
  MEM[(struct  &)this_4(D)] ={v} {CLOBBER};
  return;
}

Here "(struct &)" cast is turning struct J into the other, incompatible,
variant.  I can't make FE to use the type anywhere else and this is why
I do not get wrong code since we sort of ignore the clobber then
(consider that the memory it guards is not used/initialized).

Jason, is there a way to actually read/write into the copied structure?
Putting same alias set but keeping canonical types different comfuses
same_type_for_tbaa, is there a reason why we do not make canonical types
same?

It seems to me that we want
 1) use same TYPE_CANONICAL for both variants of the type
 2) teach LTO canonical type merging about fake bases (i.e. add a
    middle-end flag to do so).
Or can we avoid these types from getting into instruction stream?
(I suppose not - I guess point of using them in clobber is to get the
size right)

Honza

Reply via email to