https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102876

--- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to Jason Merrill from comment #9)
> (In reply to Jakub Jelinek from comment #8)
> > But I'm worried about larger TUs where not all dynamic initialization can be
> > optimized into constants.  E.g. if there remain any function calls where the
> > alias analysis could think they can read or modify the vars or their
> > subobjects etc., we'd need to punt.
> 
> Would we?  If the variable isn't const, it's OK for later initializers to
> modify its value, I wouldn't think that would prevent us from turning its
> initializer into a constant value.

I'm talking about e.g.
extern int b;
int foo (int &);
int bar (int &);
int baz () { return 1; }
int qux () { return b = 2; }
int a = foo (b);
int b = baz ();
int c = bar (b);
int d = qux ();
Here, b is initialized to constant 1 and we could optimize it into
.data
b: .long 1
or so and similarly d can be optimized into
.data
d: .long 2, but after IPA we see something like:
  _3 = foo (&b);
  a = _3;
  b = 1;
  _4 = bar (&b);
  c = _4;
  b = 2;
  d = 2;
where the fact that foo can only remember b's address somewhere, but can't
really access it because it hasn't been constructed yet is not visible.
So we'd just punt at optimizing that, we don't know if b is read or written by
foo (and, note, it doesn't have to be just the case of explicitly being passed
address of some var, it can get the address through other means).
On the other side, we can't optimize b to b: .long 2, because bar can use the
variable and/or modify it, so by using 2 as static initializer bar would be
miscompiled.
By turning the above into:
  .INIT_START (&a);
  _3 = foo (&b);
  a = _3;
  .INIT_END (&a);
  .INIT_START (&b);
  b = 1;
  .INIT_END (&b);
  .INIT_START (&c);
  _4 = bar (&b);
  c = _4;
  .INIT_END (&c);
  .INIT_START (&d);
  b = 2;
  d = 2;
  .INIT_END (&d);
we can optimize it into:
  _3 = foo (&b);
  a = _3;
  _4 = bar (&b);
  c = _4;
  b = 2;
with DECL_INITIAL (b) = 1 and DECL_INITIAL (d) = 2.
Not showing here any aggregate initializations, there we'd need to reconstruct
the CONSTRUCTOR for DECL_INITIAL from often more than one store.

> This seems like a more general issue: after a variable declared const has
> completed its initialization, it can't be modified.  Would this be useful to
> mark, kind of like we use a clobber for end of life?

I guess we could, but for this optimization we need it not just for const vars,
but also non-const.  And it isn't clear to me for what exactly we'd use it.

> Can't you just look at the type?

Probably.

Reply via email to