This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Handle OBJ_TYPE_REF in FRE
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: Richard Biener <rguenther at suse dot de>
- Cc: Jan Hubicka <hubicka at ucw dot cz>, gcc-patches at gcc dot gnu dot org
- Date: Fri, 4 Dec 2015 10:30:55 +0100
- Subject: Re: [PATCH] Handle OBJ_TYPE_REF in FRE
- Authentication-results: sourceware.org; auth=none
- References: <alpine dot LSU dot 2 dot 11 dot 1512031142360 dot 4884 at t29 dot fhfr dot qr> <20151203174007 dot GA59701 at kam dot mff dot cuni dot cz> <133CDD55-7EFC-41F9-81C1-BEC5717A9984 at suse dot de> <20151203225233 dot GA56018 at kam dot mff dot cuni dot cz> <alpine dot LSU dot 2 dot 11 dot 1512040930210 dot 4884 at t29 dot fhfr dot qr>
> 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 <rguenther@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. */