Hello, this patch adds OBJ_TYPE_REF that is the only code handled by ipa-icf-gimple but not bu operand_equal_p. I tried to make the following testcase:
/* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-pre" } */ struct foo { virtual int test (); }; int ret (struct foo *f, int v) { return v ? f->test() : f->test(); } /* { dg-final { scan-tree-dump-not "if " "pre"} } */ But we fail to tailmerge the code: <bb 2>: if (v_3(D) != 0) goto <bb 3>; else goto <bb 4>; <bb 3>: _6 = f_5(D)->_vptr.foo; _7 = *_6; _9 = OBJ_TYPE_REF(_7;(struct foo)f_5(D)->0) (f_5(D)); [tail call] goto <bb 5>; <bb 4>: _10 = f_5(D)->_vptr.foo; _11 = *_10; _13 = OBJ_TYPE_REF(_11;(struct foo)f_5(D)->0) (f_5(D)); [tail call] This is because the OBJ_TYPE_REF are not equal without unifing _7 with _11 and _6 with _10 that we don't do, because we don't have head merging. We ought to be able to do so once tail merge is witched to ipa-icf-gimple and ipa-icf-gimple to operand_equal_p. Otherwsie i think we are hitting to limitation of tree-ssa-sccvn that may want similar matching somewhere. Once I have bit of time I will work on removing of OBJ_TYPE_REF wrappers produced by objective-C in gimplification and then all the virtual_method_call_p calls can go. The naive approach of simply not building them does not work, perhaps we want to have separate OBJC tree code, since they do not really represent virtual calls after all, but I got stuck on adding new tree codes to objc becuase handling of tree.def between C/C++/obj-C/obj-C++ FEs is very convoluted. Bootstrapped/regtested x86_64-linx, OK? Honza * fold-const.c (operand_equal_p): Handle OBJ_TYPE_REF Index: fold-const.c =================================================================== --- fold-const.c (revision 229278) +++ fold-const.c (working copy) @@ -3085,6 +3082,27 @@ operand_equal_p (const_tree arg0, const_ case DOT_PROD_EXPR: return OP_SAME (0) && OP_SAME (1) && OP_SAME (2); + case OBJ_TYPE_REF: + /* OBJ_TYPE_REF is just a wrapper around OBJ_TYP_REF_EXPR. */ + if (!operand_equal_p (OBJ_TYPE_REF_EXPR (arg0), + OBJ_TYPE_REF_EXPR (arg1), flags)) + return false; + + /* Objective-C frontend produce ill formed OBJ_TYPE_REF which + probably should be dropped before reaching middle-end. */ + if (!virtual_method_call_p (arg0) || !virtual_method_call_p (arg1)) + return false; + + /* Match the type information stored in the wrapper. */ + + flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF); + return (tree_to_uhwi (OBJ_TYPE_REF_TOKEN (arg0)) + == tree_to_uhwi (OBJ_TYPE_REF_TOKEN (arg1)) + && types_same_for_odr (obj_type_ref_class (arg0), + obj_type_ref_class (arg1)) + && operand_equal_p (OBJ_TYPE_REF_OBJECT (arg0), + OBJ_TYPE_REF_OBJECT (arg1), + flags)); default: return 0; }