[PATCH] c++, dyninit: Optimize C++ dynamic initialization by constants into DECL_INITIAL adjustment [PR102876]

Richard Biener rguenther@suse.de
Fri Nov 5 10:44:53 GMT 2021

On Thu, 4 Nov 2021, Jakub Jelinek wrote:

> On Thu, Nov 04, 2021 at 12:13:51PM +0100, Richard Biener wrote:
> > As a general comment I wonder whether doing this fully in the C++
> > frontend leveraging the constexpr support is a better approach, esp.
> > before we end up putting all initializers into a single function ...
> > even partly constexpr evaluating things might help in some case.
> I initially thought that is what we should do, but I agree with Jason
> that it isn't either/or, while we should keep investigating the
> auto-constexpr handling for inline functions (curious about details for
> that, e.g. should those implicit constexpr be just a different flag
> from what we currently use, so that we e.g. ignore them during manifestly
> constant evaluation and only handle them when doing optimization only
> constant evaluation?  Do we want to copy their bodies early before all
> cp_fold like we do for real constexpr functions, or can we process
> them on their cp_folded bodies before gimplification (gimplification
> is destructive, so after that we couldn't use those obviously)?),
> that still won't handle cases of functions not marked inline, functions
> with bodies defined only after the variable with dynamic initialization,
> functions with bodies in different TUs with LTO, etc.
> Or e.g. strict C++ says something isn't valid in constant expressions,
> reinterpret_cast, etc., but our optimizers handle it fine and we still
> optimize into constant stores.

Agreed that we should attack it from both sides, I just had the
impression that most bugreports complain that clang++ can do it
and those mostly looked opportunities that could be leveraged
by simply const-evaluating the initializer. So I wonder if we shouldn't
do that first.

> > On that note it might be worth experimenting with keeping each
> > initializer in a separate function until IPA where IPA could
> > then figure out dependences via IPA REFs (with LTO on the whole
> > program), a) diagnosing inter-CU undefined behavior, b) "fixing"
> > things by making sure the initialization happens init-before-use
> > (when there's no cycle), c) with local analysis do the promotion
> > to READONLY at IPA time and elide the function.
> I thought about separate functions, but it isn't clear to me how those
> would actually help.  Because in order to optimize the dynamic initializers
> that weren't possible to optimize with constexpr machinery, we need
> inlining, not really sure if we can rely just on just early inlining, and then
> need some constant propagation etc.  But on the other side, we don't want
> to call hundreds of different functions from the *GLOBAL_*_I_* functions,
> so even if we used separate functions, we want IPA to inline it.

All true, but at least separate functions make it easier to see what
the initializer is without resorting to tricks like the internal functions
you add (just guessing a bit, didn't look at the patch yet).

Say, if the CTOR function has

  a = 2;
  b = foo ();
  c = 0;

coming from

int a = baz (); // returns constant 2
int b = foo (); // not resolvable
int c = bar (); // returns constant 0

then how do we know that foo () does not modify a[] or c[]?
At least modifying c from foo () should be UB?  modifying a
might be OK.  But with

  a = 2;
  b = foo ();
  c = 0;

we need to prove we can move the inits before any possible clobbers
to make them static inits?  Promoting a is OK I guess since foo ()
will simply re-initialize it.  But promoting c is only OK if
foo modifying it would be UB.

> For the diagnostics of UB, we have -fsanitize=address which should diagnose
> incorrect initialization ordering.

Ah, I see.  Of course that doesn't diagnose things that are UB but
happen to be "corrected" by link order?


More information about the Gcc-patches mailing list