This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH, PR 45699] Devirtualize to thunks
- From: Richard Guenther <rguenther at suse dot de>
- To: Martin Jambor <mjambor at suse dot cz>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>, Jan Hubicka <hubicka at ucw dot cz>
- Date: Mon, 11 Oct 2010 15:56:01 +0200 (CEST)
- Subject: Re: [PATCH, PR 45699] Devirtualize to thunks
- References: <20101011133014.GA12977@virgil.arch.suse.de>
On Mon, 11 Oct 2010, Martin Jambor wrote:
> Hi,
>
> folding of OBJ_TYPE_REFs just takes the function declaration in BINFOs
> and puts into the call statement. Unfortunately BINFOs do not put the
> declaration of the proper thunk there and so we might ending up not
> adjusting the this pointer like in the testcase below. On the other
> hand, BINFOs do contain the deltas and so the folding code can look up
> the right thunk in the call graph if need be. This is what the patch
> below does.
>
> Bootstrapped and tested on x86_64-linux without any issues. OK for
> trunk?
Ok.
Thanks,
Richard.
> Thanks,
>
> Martin
>
>
> 2010-10-08 Martin Jambor <mjambor@suse.cz>
>
> PR middle-end/45699
> * gimple-fold.c (gimple_fold_obj_type_ref_known_binfo): Choose among
> thunks.
>
> * testsuite/g++.dg/torture/pr45699.C: New test.
> * testsuite/g++.dg/otr-fold-1.C: Adjusted.
> * testsuite/g++.dg/otr-fold-1.C: Likewise.
>
>
> Index: icln/gcc/gimple-fold.c
> ===================================================================
> --- icln.orig/gcc/gimple-fold.c
> +++ icln/gcc/gimple-fold.c
> @@ -1463,7 +1463,7 @@ tree
> gimple_fold_obj_type_ref_known_binfo (HOST_WIDE_INT token, tree known_binfo)
> {
> HOST_WIDE_INT i;
> - tree v, fndecl;
> + tree v, fndecl, delta;
>
> v = BINFO_VIRTUALS (known_binfo);
> i = 0;
> @@ -1475,6 +1475,25 @@ gimple_fold_obj_type_ref_known_binfo (HO
> }
>
> fndecl = TREE_VALUE (v);
> + delta = TREE_PURPOSE (v);
> + gcc_assert (host_integerp (delta, 0));
> +
> + if (integer_nonzerop (delta))
> + {
> + struct cgraph_node *node = cgraph_get_node (fndecl);
> + HOST_WIDE_INT off = tree_low_cst (delta, 0);
> +
> + if (!node)
> + return NULL;
> + for (node = node->same_body; node; node = node->next)
> + if (node->thunk.thunk_p && off == node->thunk.fixed_offset)
> + break;
> + if (node)
> + fndecl = node->decl;
> + else
> + return NULL;
> + }
> +
> /* When cgraph node is missing and function is not public, we cannot
> devirtualize. This can happen in WHOPR when the actual method
> ends up in other partition, because we found devirtualization
> Index: icln/gcc/testsuite/g++.dg/otr-fold-1.C
> ===================================================================
> --- icln.orig/gcc/testsuite/g++.dg/otr-fold-1.C
> +++ icln/gcc/testsuite/g++.dg/otr-fold-1.C
> @@ -72,5 +72,5 @@ int main (int argc, char *argv[])
> return 0;
> }
>
> -/* { dg-final { scan-tree-dump "= B::foo" "optimized" } } */
> +/* { dg-final { scan-tree-dump "= B::.*foo" "optimized" } } */
> /* { dg-final { cleanup-tree-dump "optimized" } } */
> Index: icln/gcc/testsuite/g++.dg/otr-fold-2.C
> ===================================================================
> --- icln.orig/gcc/testsuite/g++.dg/otr-fold-2.C
> +++ icln/gcc/testsuite/g++.dg/otr-fold-2.C
> @@ -84,5 +84,5 @@ int main (int argc, char *argv[])
> return 0;
> }
>
> -/* { dg-final { scan-tree-dump "= B::foo" "optimized" } } */
> +/* { dg-final { scan-tree-dump "= B::.*foo" "optimized" } } */
> /* { dg-final { cleanup-tree-dump "optimized" } } */
> Index: icln/gcc/testsuite/g++.dg/torture/pr45699.C
> ===================================================================
> --- /dev/null
> +++ icln/gcc/testsuite/g++.dg/torture/pr45699.C
> @@ -0,0 +1,61 @@
> +// { dg-do run }
> +
> +extern "C" void abort ();
> +
> +class A
> +{
> +public:
> + virtual void foo () {abort();}
> +};
> +
> +class B : public A
> +{
> +public:
> + int z;
> + virtual void foo () {abort();}
> +};
> +
> +class C : public A
> +{
> +public:
> + void *a[32];
> + unsigned long b;
> + long c[32];
> +
> + virtual void foo () {abort();}
> +};
> +
> +class D : public C, public B
> +{
> +public:
> + D () : C(), B()
> + {
> + int i;
> + for (i = 0; i < 32; i++)
> + {
> + a[i] = (void *) 0;
> + c[i] = 0;
> + }
> + b = 0xaaaa;
> + }
> +
> + virtual void foo ();
> +};
> +
> +void D::foo()
> +{
> + if (b != 0xaaaa)
> + abort();
> +}
> +
> +static inline void bar (B &b)
> +{
> + b.foo ();
> +}
> +
> +int main()
> +{
> + D d;
> + bar (d);
> + return 0;
> +}
>
>
--
Richard Guenther <rguenther@suse.de>
Novell / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 - GF: Markus Rex