Hi,

On Thu, Jul 14 2022, Richard Biener wrote:
> On Wed, Jul 13, 2022 at 11:06 PM Martin Jambor <mjam...@suse.cz> wrote:
>>
>> Hi,
>>
>> with -fno-toplevel-reorder (and -fwhole-program), there apparently can
>> be local functions without any callers.
>
> Did you check why?  Can't we fix that?

no, I have not checked much.

Our manual description of -fno-toplevel-reorder says that:

  "When this option is used, unreferenced static variables are not
   removed."

In the beginning, static (because of -fwhole-program) variables _ZTV1S
and __gxx_personality_v0 do refer to the destructor in question, my
hypothesis is that the dead function removal code somehow has to be
careful in case these have been already output, even when these two
variables are no longer in the symbol table when IPA-CP runs.

But I did not look deeper, hoping that Honza would correct me if I am
totally off.  Perhaps the bug is that the function should not be local
even with -fwhole-program.  The semantics of this combination of options
is a bit unclear to me.

Martin


>
>>  This is something that IPA-CP
>> does not like because its propagation verifier checks that local
>> functions do not end up with TOP in their lattices.  Therefore there
>> is an assert checking that all call-less unreachable functions have
>> been removed, which triggers in PR 106260 with these two options.
>>
>> This patch detects the situation and marks the lattices as variable,
>> thus avoiding both the assert trigger and the verification failure.
>>
>> Bootstrapped and tested on x86_64-linux.  OK for master and then all
>> active release branches?
>>
>> Thanks,
>>
>> Martin
>>
>>
>> gcc/ChangeLog:
>>
>> 2022-07-13  Martin Jambor  <mjam...@suse.cz>
>>
>>         PR ipa/106260
>>         * ipa-cp.cc (initialize_node_lattices): Replace assert that there are
>>         callers with handling that situation when -fno-toplevel_reorder.
>>
>> gcc/testsuite/ChangeLog:
>>
>> 2022-07-13  Martin Jambor  <mjam...@suse.cz>
>>
>>         PR ipa/106260
>>         * g++.dg/ipa/pr106260.C: New test.
>> ---
>>  gcc/ipa-cp.cc                       |  6 ++-
>>  gcc/testsuite/g++.dg/ipa/pr106260.C | 64 +++++++++++++++++++++++++++++
>>  2 files changed, 69 insertions(+), 1 deletion(-)
>>  create mode 100644 gcc/testsuite/g++.dg/ipa/pr106260.C
>>
>> diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
>> index 543a9334e2c..f699a8dadc0 100644
>> --- a/gcc/ipa-cp.cc
>> +++ b/gcc/ipa-cp.cc
>> @@ -1286,10 +1286,14 @@ initialize_node_lattices (struct cgraph_node *node)
>>        int caller_count = 0;
>>        node->call_for_symbol_thunks_and_aliases (count_callers, 
>> &caller_count,
>>                                                 true);
>> -      gcc_checking_assert (caller_count > 0);
>>        if (caller_count == 1)
>>         node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
>>                                                   NULL, true);
>> +      else if (caller_count == 0)
>> +       {
>> +         gcc_checking_assert (!opt_for_fn (node->decl, 
>> flag_toplevel_reorder));
>> +         variable = true;
>> +       }
>>      }
>>    else
>>      {
>> diff --git a/gcc/testsuite/g++.dg/ipa/pr106260.C 
>> b/gcc/testsuite/g++.dg/ipa/pr106260.C
>> new file mode 100644
>> index 00000000000..bd3b6e0af79
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.dg/ipa/pr106260.C
>> @@ -0,0 +1,64 @@
>> +// { dg-do compile }
>> +// { dg-options "-O2 -std=gnu++14 -fwhole-program -fno-unit-at-a-time" }
>> +
>> +struct A;
>> +template <class T>
>> +struct Q { Q (T); };
>> +template<typename T, class D>
>> +struct U {
>> +  ~U () { m1 (nullptr); }
>> +  D m2 ();
>> +  T *u;
>> +  void m1 (T *) { m2 () (u); }
>> +};
>> +struct F { F (int *); };
>> +template <class, class T = F>
>> +using W = Q<T>;
>> +int a, b;
>> +void fn1 (void *);
>> +template <class T>
>> +void
>> +fn2 (T *x)
>> +{
>> +  if (x)
>> +    x->~T();
>> +  fn1 (x);
>> +}
>> +template <typename T>
>> +struct C {
>> +  void operator() (T *x) { fn2 (x); }
>> +};
>> +struct D;
>> +template <typename T, typename D = C<T> >
>> +using V = U<T, D>;
>> +struct A {
>> +  A (int *);
>> +};
>> +struct S;
>> +struct G {
>> +  V<S> m3 ();
>> +};
>> +struct S {
>> +  int e;
>> +  virtual ~S () {}
>> +};
>> +template<typename T>
>> +struct H {
>> +  H (int, T x, int) : h(x) {}
>> +  G g;
>> +  void m4 () { g.m3 (); }
>> +  T h;
>> +};
>> +struct I {
>> +  I(A, W<D>);
>> +};
>> +void
>> +test ()
>> +{
>> +  A c (&b);
>> +  W<D> d (&b);
>> +  I e (c, d);
>> +  H<I> f (0, e, a);
>> +  f.m4 ();
>> +}
>> +
>> --
>> 2.36.1
>>

Reply via email to