> Hi,
> 
> on the 4.7 branch just like on the newer one, I'd like to fix the bug
> by simply never propagating through thunks.  There even less pre-IPA
> devirtualization going on and so this should have minimal impact.
> 
> Bootstrapped and tested on x86_64.  OK for the branch?

OK for both branches.

Honza
> 
> Thanks,
> 
> Martin
> 
> 
> 2014-04-01  Martin Jambor  <mjam...@suse.cz>
> 
>       PR ipa/60640
>       * ipa-cp.c (propagate_constants_accross_call): Do not propagate
>       accross thunks.
> 
> testsuite/
>         * g++.dg/ipa/pr60640-1.C: New test.
>         * g++.dg/ipa/pr60640-2.C: Likewise.
>         * g++.dg/ipa/pr60640-3.C: Likewise.
> 
> diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
> index 454283a..ddf6605 100644
> --- a/gcc/ipa-cp.c
> +++ b/gcc/ipa-cp.c
> @@ -1063,21 +1063,21 @@ propagate_constants_accross_call (struct cgraph_edge 
> *cs)
>    args_count = ipa_get_cs_argument_count (args);
>    parms_count = ipa_get_param_count (callee_info);
>  
> -  /* If this call goes through a thunk we must not propagate to the first 
> (0th)
> -     parameter.  However, we might need to uncover a thunk from below a 
> series
> -     of aliases first.  */
> +  /* If this call goes through a thunk we should not propagate because we
> +     cannot redirect edges to thunks.  However, we might need to uncover a
> +     thunk from below a series of aliases first.  */
>    alias_or_thunk = cs->callee;
>    while (alias_or_thunk->alias)
>      alias_or_thunk = cgraph_alias_aliased_node (alias_or_thunk);
>    if (alias_or_thunk->thunk.thunk_p)
>      {
> -      ret |= set_lattice_contains_variable (ipa_get_lattice (callee_info, 
> 0));
> -      i = 1;
> +      for (i = 0; i < parms_count; i++)
> +     ret |= set_lattice_contains_variable (ipa_get_lattice (callee_info, i));
> +
> +      return ret;
>      }
> -  else
> -    i = 0;
>  
> -  for (; (i < args_count) && (i < parms_count); i++)
> +  for (i = 0; (i < args_count) && (i < parms_count); i++)
>      {
>        struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
>        struct ipcp_lattice *dest_lat = ipa_get_lattice (callee_info, i);
> diff --git a/gcc/testsuite/g++.dg/ipa/pr60640-1.C 
> b/gcc/testsuite/g++.dg/ipa/pr60640-1.C
> new file mode 100644
> index 0000000..7a0b918
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ipa/pr60640-1.C
> @@ -0,0 +1,50 @@
> +// { dg-do compile }
> +// { dg-options "-O3" }
> +
> +class ASN1Object
> +{
> +public:
> +  virtual ~ASN1Object ();
> +};
> +class A
> +{
> +  virtual unsigned m_fn1 () const;
> +};
> +class B
> +{
> +public:
> +  ASN1Object Element;
> +  virtual unsigned m_fn1 (bool) const;
> +};
> +template <class BASE> class C : public BASE
> +{
> +};
> +
> +class D : ASN1Object, public B
> +{
> +};
> +class G : public D
> +{
> +  unsigned m_fn1 (bool) const {}
> +};
> +class F : A
> +{
> +public:
> +  F (A);
> +  unsigned m_fn1 () const
> +  {
> +    int a;
> +    a = m_fn2 ().m_fn1 (0);
> +    return a;
> +  }
> +  const B &m_fn2 () const { return m_groupParameters; }
> +  C<G> m_groupParameters;
> +};
> +template <class D> void BenchMarkKeyAgreement (int *, int *, int)
> +{
> +  A f;
> +  D d (f);
> +}
> +
> +void BenchmarkAll2 () { BenchMarkKeyAgreement<F>(0, 0, 0); }
> +
> diff --git a/gcc/testsuite/g++.dg/ipa/pr60640-2.C 
> b/gcc/testsuite/g++.dg/ipa/pr60640-2.C
> new file mode 100644
> index 0000000..c6e614c
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ipa/pr60640-2.C
> @@ -0,0 +1,15 @@
> +// { dg-do compile }
> +// { dg-options "-O3" }
> +
> +struct B { virtual unsigned f () const; };
> +struct C { virtual void f (); };
> +struct F { virtual unsigned f (bool) const; ~F (); };
> +struct J : C, F {};
> +struct G : J { unsigned f (bool) const { return 0; } };
> +struct H : B
> +{
> +  H (int);
> +  unsigned f () const { return ((const F &) h).f (0); }
> +  G h;
> +};
> +H h (0);
> diff --git a/gcc/testsuite/g++.dg/ipa/pr60640-3.C 
> b/gcc/testsuite/g++.dg/ipa/pr60640-3.C
> new file mode 100644
> index 0000000..21b1f58
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ipa/pr60640-3.C
> @@ -0,0 +1,81 @@
> +// { dg-do run }
> +// { dg-options "-O3" }
> +
> +struct Distraction
> +{
> +  char fc[8];
> +  virtual Distraction * return_self ()
> +  { return this; }
> +};
> +
> +namespace {
> +
> +struct A;
> +static A * __attribute__ ((noinline, noclone)) get_an_A ();
> +
> +static int go;
> +
> +struct A
> +{
> +  int fi;
> +
> +  A () : fi(777) {}
> +  A (int pi) : fi (pi) {}
> +  virtual A * foo (int p) = 0;
> +};
> +
> +struct B;
> +static B * __attribute__ ((noinline, noclone)) get_a_B ();
> +
> +struct B : public Distraction, A
> +{
> +  B () : Distraction(), A() { }
> +  B (int pi) : Distraction (), A (pi) {}
> +  virtual B * foo (int p)
> +  {
> +    int o = fi;
> +    for (int i = 0; i < p; i++)
> +      o += i + i * i;
> +    go = o;
> +
> +    return get_a_B ();
> +  }
> +};
> +
> +
> +struct B gb1 (1111), gb2 (2);
> +static B * __attribute__ ((noinline, noclone))
> +get_a_B ()
> +{
> +  return &gb1;
> +}
> +
> +static A * __attribute__ ((noinline, noclone))
> +get_an_A ()
> +{
> +  return &gb2;
> +}
> +
> +}
> +
> +static int __attribute__ ((noinline, noclone))
> +get_a_number ()
> +{
> +  return 5;
> +}
> +
> +extern "C" void abort (void);
> +
> +int main (int argc, char *argv[])
> +{
> +  for (int i = 0; i < get_a_number (); i++)
> +    {
> +      struct A *p = get_an_A ();
> +      struct A *r = p->foo (4);
> +      if (r->fi != 1111)
> +     abort ();
> +      if (go != 22)
> +     abort ();
> +    }
> +  return 0;
> +}

Reply via email to