> >may lead to wrong code.
> 
> Can you try generating a testcase?
>  Because with equal vptr and voffset I can't see how that can happen unless 
> some pass extracts information from the pointer types without sanity checking 
> with the pointers and offsets.

I am not sure I can get a wrong code with current mainline, because for now you
only substitute for the lookup done for speculative devirt and if we wrongly
predict the thing to be __builtin_unreachable, we dispatch to usual virtual
call.  Once you get movement on calls it will be easier to do.

OBJ_TYPE_REF is a wrapper around OBJ_TYPE_EXPR adding three extra parameters:
 - OBJ_TYPE_REF_OBJECT
 - OBJ_TYPE_REF_TOKEN
 - obj_type_ref_class which is computed from TREE_TYPE (obj_type_ref) itself.

While two OBJ_TYPE_REFS with equivalent OBJ_TYPE_EXPR are kind of same
expressions, they are optimized differently (just as if they was in different
alias set).  For that reason you need to match the type of obj_type_ref_class
because that one is not matched by usless_type_conversion (it is a pointer to
method of corresponding class type we are looking up)

The following testcase:
struct foo {virtual void bar(void) __attribute__ ((const));};
struct foobar {virtual void bar(void) __attribute__ ((const));};
void
dojob(void *ptr, int t)
{
  if (t)
   ((struct foo*)ptr)->bar();
  else
   ((struct foobar*)ptr)->bar();
}

produces
void dojob(void*, int) (void * ptr, int t)
{
  int (*__vtbl_ptr_type) () * _5;
  int (*__vtbl_ptr_type) () _6;
  int (*__vtbl_ptr_type) () * _8;
  int (*__vtbl_ptr_type) () _9;

  <bb 2>:
  if (t_2(D) != 0)
    goto <bb 3>;
  else
    goto <bb 4>;

  <bb 3>:
  _5 = MEM[(struct foo *)ptr_4(D)]._vptr.foo;
  _6 = *_5;
  OBJ_TYPE_REF(_6;(struct foo)ptr_4(D)->0) (ptr_4(D));
  goto <bb 5>;

  <bb 4>:
  _8 = MEM[(struct foobar *)ptr_4(D)]._vptr.foobar;
  _9 = *_8;
  OBJ_TYPE_REF(_9;(struct foobar)ptr_4(D)->0) (ptr_4(D));

  <bb 5>:
  return;

}

Now I would need to get some code movement done to get _5 and _6
moved and unified with _8 and _9 that we currently don't do.  
Still would feel safer if the equivalence predicate also checked
that the type is the same.
> >Or do you just substitute the operands of OBJ_TYPE_REF? 
> 
> No, I value number them.  But yes, the type issue also crossed my mind.  
> Meanwhile testing revealed that I need to adjust gimple_expr_type to preserve 
> the type of the obj-type-ref, otherwise the devirt machinery ICEs (receiving 
> void *). That's also a reason we can't make obj-type-ref a ternary RHS.

Yep, type of OBJ_TYPE_REF matters...
> 
> >> Bootstrap & regtest running on x86_64-unknown-linux-gnu.
> >> 
> >> Note that this does not (yet) substitute OBJ_TYPE_REFs in calls
> >> with SSA names that have the same value - not sure if that would
> >> be desired generally (does the devirt machinery cope with that?).
> >
> >This should work fine.
> 
> OK. So with that substituting the direct call later should work as well.
Great!
> 
> Richard.

Honza
> 
> >> 
> >> Thanks,
> >> Richard.
> >> 
> >> 2015-12-03  Richard Biener  <rguent...@suse.de>
> >> 
> >>    PR tree-optimization/64812
> >>    * tree-ssa-sccvn.c (vn_get_stmt_kind): Handle OBJ_TYPE_REF.
> >>    (vn_nary_length_from_stmt): Likewise.
> >>    (init_vn_nary_op_from_stmt): Likewise.
> >>    * gimple-match-head.c (maybe_build_generic_op): Likewise.
> >>    * gimple-pretty-print.c (dump_unary_rhs): Likewise.
> >> 
> >>    * g++.dg/tree-ssa/ssa-fre-1.C: New testcase.
> >> 
> >> Index: gcc/tree-ssa-sccvn.c
> >> ===================================================================
> >> *** gcc/tree-ssa-sccvn.c   (revision 231221)
> >> --- gcc/tree-ssa-sccvn.c   (working copy)
> >> *************** vn_get_stmt_kind (gimple *stmt)
> >> *** 460,465 ****
> >> --- 460,467 ----
> >>                      ? VN_CONSTANT : VN_REFERENCE);
> >>            else if (code == CONSTRUCTOR)
> >>              return VN_NARY;
> >> +          else if (code == OBJ_TYPE_REF)
> >> +            return VN_NARY;
> >>            return VN_NONE;
> >>          }
> >>      default:
> >> *************** vn_nary_length_from_stmt (gimple *stmt)
> >> *** 2479,2484 ****
> >> --- 2481,2487 ----
> >>         return 1;
> >>   
> >>       case BIT_FIELD_REF:
> >> +     case OBJ_TYPE_REF:
> >>         return 3;
> >>   
> >>       case CONSTRUCTOR:
> >> *************** init_vn_nary_op_from_stmt (vn_nary_op_t
> >> *** 2508,2513 ****
> >> --- 2511,2517 ----
> >>         break;
> >>   
> >>       case BIT_FIELD_REF:
> >> +     case OBJ_TYPE_REF:
> >>         vno->length = 3;
> >>         vno->op[0] = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
> >>         vno->op[1] = TREE_OPERAND (gimple_assign_rhs1 (stmt), 1);
> >> Index: gcc/gimple-match-head.c
> >> ===================================================================
> >> *** gcc/gimple-match-head.c        (revision 231221)
> >> --- gcc/gimple-match-head.c        (working copy)
> >> *************** maybe_build_generic_op (enum tree_code c
> >> *** 243,248 ****
> >> --- 243,249 ----
> >>         *op0 = build1 (code, type, *op0);
> >>         break;
> >>       case BIT_FIELD_REF:
> >> +     case OBJ_TYPE_REF:
> >>         *op0 = build3 (code, type, *op0, op1, op2);
> >>         break;
> >>       default:;
> >> Index: gcc/gimple-pretty-print.c
> >> ===================================================================
> >> *** gcc/gimple-pretty-print.c      (revision 231221)
> >> --- gcc/gimple-pretty-print.c      (working copy)
> >> *************** dump_unary_rhs (pretty_printer *buffer,
> >> *** 302,308 ****
> >>      || TREE_CODE_CLASS (rhs_code) == tcc_reference
> >>      || rhs_code == SSA_NAME
> >>      || rhs_code == ADDR_EXPR
> >> !    || rhs_code == CONSTRUCTOR)
> >>    {
> >>      dump_generic_node (buffer, rhs, spc, flags, false);
> >>      break;
> >> --- 302,309 ----
> >>      || TREE_CODE_CLASS (rhs_code) == tcc_reference
> >>      || rhs_code == SSA_NAME
> >>      || rhs_code == ADDR_EXPR
> >> !    || rhs_code == CONSTRUCTOR
> >> !    || rhs_code == OBJ_TYPE_REF)
> >>    {
> >>      dump_generic_node (buffer, rhs, spc, flags, false);
> >>      break;
> >> Index: gcc/testsuite/g++.dg/tree-ssa/ssa-fre-1.C
> >> ===================================================================
> >> *** gcc/testsuite/g++.dg/tree-ssa/ssa-fre-1.C      (revision 0)
> >> --- gcc/testsuite/g++.dg/tree-ssa/ssa-fre-1.C      (working copy)
> >> ***************
> >> *** 0 ****
> >> --- 1,44 ----
> >> + /* { dg-do compile } */
> >> + /* { dg-options "-O2 -fdump-tree-fre2" } */
> >> + 
> >> + template <class T> class A
> >> + {
> >> +   T *p;
> >> + 
> >> + public:
> >> +   A (T *p1) : p (p1) { p->acquire (); }
> >> + };
> >> + 
> >> + class B
> >> + {
> >> + public:
> >> +     virtual void acquire ();
> >> + };
> >> + class D : public B
> >> + {
> >> + };
> >> + class F : B
> >> + {
> >> +   int mrContext;
> >> + };
> >> + class WindowListenerMultiplexer : F, public D
> >> + {
> >> +   void acquire () { acquire (); }
> >> + };
> >> + class C
> >> + {
> >> +   void createPeer () throw ();
> >> +   WindowListenerMultiplexer maWindowListeners;
> >> + };
> >> + class FmXGridPeer
> >> + {
> >> + public:
> >> +     void addWindowListener (A<D>);
> >> + } a;
> >> + void
> >> + C::createPeer () throw ()
> >> + {
> >> +   a.addWindowListener (&maWindowListeners);
> >> + }
> >> + 
> >> + /* { dg-final { scan-tree-dump-times "= OBJ_TYPE_REF" 1 "fre2" } }
> >*/
> 

Reply via email to