Message ID | alpine.LSU.2.11.1512040930210.4884@t29.fhfr.qr |
---|---|
State | New |
Headers | show |
> 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. */
On Fri, 4 Dec 2015, Jan Hubicka wrote: > > 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. Even better. Make it a tcc_reference tree then. > > > > 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. Btw, might be necessary for targets with function descriptors - not sure though. Richard. > > > > 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. */ > >
> On Fri, 4 Dec 2015, Jan Hubicka wrote: > > > > 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. > > Even better. Make it a tcc_reference tree then. makes sense to me - it is indeed more similar to MEM_REF than to an expression. I will look into that next stage1. Honza
Index: gcc/tree-ssa-pre.c =================================================================== --- gcc/tree-ssa-pre.c (revision 231244) +++ gcc/tree-ssa-pre.c (working copy) @@ -4334,6 +4334,22 @@ eliminate_dom_walker::before_dom_childre maybe_remove_unused_call_args (cfun, call_stmt); gimple_set_modified (stmt, true); } + + else + { + /* Lookup the OBJ_TYPE_REF. */ + tree sprime + = vn_nary_op_lookup_pieces (3, OBJ_TYPE_REF, + TREE_TYPE (fn), + &TREE_OPERAND (fn, 0), NULL); + if (sprime) + sprime = eliminate_avail (sprime); + if (sprime) + { + gimple_call_set_fn (call_stmt, sprime); + gimple_set_modified (stmt, true); + } + } } } but it ICEs because we decided (tree-cfg.c, verify_gimple_call): 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; 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. 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. */