> Indeed we don't do code hoisting yet. Maybe one could trick PPRE > into doing it. > > Note that for OBJ_TYPE_REFs in calls you probably should better use > gimple_call_fntype instead of the type of the OBJ_TYPE_REF anyway > (well, fntype will be the method-type, not pointer-to-method-type). > > Not sure if you need OBJ_TYPE_REFs type in non-call contexts?
Well, to optimize speculative call sequences if (funptr == thismethod) inlined this method body else funptr (); Here you want to devirtualize the conditional, not the call in order to get the inlined method unconditonally. In general I think OBJ_TYPE_REF is misplaced - it should be on vtable load instead of the call/conditional. It is a property of the vtable lookup. Then it would work for method pointers too. > > if (fn > && (!POINTER_TYPE_P (TREE_TYPE (fn)) > || (TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != FUNCTION_TYPE > && TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != METHOD_TYPE))) > { > error ("non-function in gimple call"); > return true; > } > > and in useless_type_conversion_p: > > /* Do not lose casts to function pointer types. */ > if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE > || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE) > && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE > || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE)) > return false; Yeah, this does not make much sense to me anymore. Something to track next stage1. > > probably from the times we didn't have gimple_call_fntype. So if I > paper over the ICE (in the verifier) then the libreoffice testcase > gets optimized to > > <bb 2>: > _3 = this_2(D)->D.2399.D.2325._vptr.B; > _4 = *_3; > PROF_6 = OBJ_TYPE_REF(_4;(struct > WindowListenerMultiplexer)this_2(D)->0); > if (PROF_6 == acquire) > goto <bb 3>; > else > goto <bb 4>; > > <bb 3>: > PROF_6 (this_2(D)); > goto <bb 5>; > > <bb 4>: > PROF_6 (this_2(D)); > > by FRE2 and either VRP or DOM will propagate the equivalency to > > <bb 2>: > _3 = this_2(D)->D.2399.D.2325._vptr.B; > _4 = *_3; > PROF_6 = OBJ_TYPE_REF(_4;(struct > WindowListenerMultiplexer)this_2(D)->0); > if (PROF_6 == acquire) > goto <bb 3>; > else > goto <bb 4>; > > <bb 3>: > WindowListenerMultiplexer::acquire (this_2(D)); > goto <bb 5>; > > <bb 4>: > PROF_6 (this_2(D)); > > Richard. LGTM. Honza > > 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. > * gimple-fold.c (gimple_build): Likewise. > * gimple.h (gimple_expr_type): 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" } } */ > Index: gcc/gimple-fold.c > =================================================================== > --- gcc/gimple-fold.c (revision 231221) > +++ gcc/gimple-fold.c (working copy) > @@ -6038,7 +6038,8 @@ gimple_build (gimple_seq *seq, location_ > else > res = create_tmp_reg (type); > gimple *stmt; > - if (code == BIT_FIELD_REF) > + if (code == BIT_FIELD_REF > + || code == OBJ_TYPE_REF) > stmt = gimple_build_assign (res, code, > build3 (code, type, op0, op1, op2)); > else > Index: gcc/gimple.h > =================================================================== > --- gcc/gimple.h (revision 231221) > +++ gcc/gimple.h (working copy) > @@ -6079,7 +6079,9 @@ gimple_expr_type (const gimple *stmt) > } > else if (code == GIMPLE_ASSIGN) > { > - if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) > + enum tree_code rcode = gimple_assign_rhs_code (stmt); > + if (rcode == POINTER_PLUS_EXPR > + || rcode == OBJ_TYPE_REF) > return TREE_TYPE (gimple_assign_rhs1 (stmt)); > else > /* As fallback use the type of the LHS. */