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, PR 45699] Devirtualize to thunks


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


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