This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Handle OBJ_TYPE_REF in FRE


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]