Bug 20319 - -fkeep-static-consts with -O asserted doesn't keep consts
Summary: -fkeep-static-consts with -O asserted doesn't keep consts
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 3.4.3
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: documentation
Depends on:
Blocks:
 
Reported: 2005-03-04 17:05 UTC by Gary Funck
Modified: 2013-11-05 21:18 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2007-11-14 03:05:49


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Gary Funck 2005-03-04 17:05:18 UTC
Related discussion:
http://gcc.gnu.org/ml/gcc/2005-03/msg00181.html

Given the following,

static char const rcsid[] =
"$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $";
int main() {}

When compiled with GCC 3.4.3, at -O2, the ident string above will _not_
appear in the executable.  This is apparently expected behavior.

However,
  gcc -fkeep-static-consts -O2 t.c
did not retain the ident string, rcsid, defined above.  Shouldn't
-fkepp-static-consts have ensured that this static constant would appear
in the executable?

The logic in wrapup_global_declarations (toplev.c) doesn't look quite right:

              else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)
                       && (optimize || !flag_keep_static_consts 
                           || DECL_ARTIFICIAL (decl))) 
                needed = 0; 

If 'optimize' is asserted above then flag_keep_static_consts will
not be tested.  Perhaps it should read as follows?

                       && ((optimize && !flag_keep_static_consts)

Alternatively, I wonder if flag_keep_static_consts should be tested earlier at a
higher level, for example:

   if (flag_keep_static_consts)
      /* needed */;

but I'm not sure about which of the earlier tests which assert needed = 0;
are mandatory and which are optional.
Comment 1 Andrew Pinski 2005-03-04 18:29:48 UTC
Nope, -fkeep-static-consts only control when optimization is not on:
From the docs:
Emit variables declared @code{static const} when optimization ____isn't____ turned
on, even if the variables aren't referenced.

Enphise mine.

Use the "used" attribute if you want to keep unused constants.
Comment 2 Gary Funck 2005-03-04 20:24:15 UTC
"Emit variables declared @code{static const} when optimization isn't turned 
on, even if the variables aren't referenced."

How odd.  I should've checked the docs, but this brief explanation in the
help line made a lot of sense to me.

  -fkeep-static-consts        Emit static const variables even if they are not
                              used

Also, since the constant *was kept* when I compiled _without_ optimization,
the idea of passing a switch telling the compiler to do something that
it seemed to already be doing by default didn't make sense to me.

The comments inside toplev.c say the following:

/* Nonzero means that we should emit static const variables
   regardless of whether or not optimization is turned on.  */ 
                            
int flag_keep_static_consts = 1;


which makes sense to me.  Note that this is the default setting.

So ... coming back to the if statement in toplev.c:

              else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)
                       && (optimize || !flag_keep_static_consts
                           || DECL_ARTIFICIAL (decl)))
                needed = 0;

At present,

If optimize is set, the unused static constant will always be eliminated
and -fkeep-static-consts will have no effect, and there is no way to override
this behavior (except for __attribute__ ((used))). 

This agrees with the documentation, but disagrees with the
comment in the code, and with the spirit of the help message.  It also
doesn't make sense to me that -fkeep-static-consts would be ignored. In
fact, it seems to me that -fkeep-static-consts should override the
optimization setting.  Otherwise, only -fno-keep-static-consts has
any effect and that is only when optimization is not enabled.

I think the behavior of -fkeep-static-consts should be modified so that
setting this switch overrides the optimization level.  Thus, the
documentation would need to be changed as well.  Otherwise, the internal
comments and the help line are wrong.

Regarding the "used" attibute, I thought that I'd tried that, and it
didn't work.  But upon retesting, it does seem to have the desired
effect of keeping the static const around (maybe I specified the "unused"
attribute by mistake in my test).

Note that the "used" attribute is described only under "function attributes"
and not under "variable attributes" in the documentation:

used
This attribute, attached to a function, means that code must be emitted for 
the function even if it appears that the function is not referenced. This is 
useful, for example, when the function is referenced only in inline assembly. 

(see: http://gcc.gnu.org/onlinedocs/gcc-3.4.3/gcc/Function-
Attributes.html#Function-Attributes)

It would be helpful if the documentation were updated to describe the
behavior of the `used' attribute when apllied to variables.
Comment 3 Andrew Pinski 2005-03-04 20:33:49 UTC
Don't belive the comments in the source.  Also the --help is way out of date. you want to use the used 
attribute like so:
static char const rcsid[]__attribute__((used)) =
"$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $";

And this works for me.
Comment 4 joseph@codesourcery.com 2005-03-04 20:42:49 UTC
Subject: Re:  -fkeep-static-consts with -O asserted doesn't keep
 consts

On Fri, 4 Mar 2005, pinskia at gcc dot gnu dot org wrote:

> Don't belive the comments in the source.  Also the --help is way out of 
> date.

Both comments being wrong and --help being wrong are bugs.  This PR should 
be kept open until whatever semantics are agreed are documented in the 
manual, in --help output, in comments and are implemented.

Comment 5 Gary Funck 2005-03-04 21:54:36 UTC

Here is some detail on my proposed change in behavior:

1) Change the default setting to -fno-keep-static-consts:

/* Nonzero means that we should emit static const variables
   regardless of whether or not optimization is turned on.  */ 
                            
int flag_keep_static_consts = 0;

2) have flag_keep_static_consts affect only the behavior of the
compiler when 'optimize' is asserted:

Change the logic in wrapup_global_declarations (toplev.c) to read:

              else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)
                       && (optimize && !flag_keep_static_consts)
                           || DECL_ARTIFICIAL (decl))) 
                needed = 0;

This change would imply that:

1) -fkeep-static-consts and -fno-keep-static-consts will have no effect
at -O0.  Presently, -fno-keep-static-consts would eliminate the unreferenced
static const variable if it isn't referenced.  This would no longer be
the case. At -O0, the compiler would always leave unrefereced static
consts alone.

2) If optimization is asserted (ie, -O1 and above), then always eliminate
static const's that aren't referenced, unless -fkeep-static-consts is
asserted.


Comment 6 Gary Funck 2005-03-18 16:16:28 UTC
from http://gcc.gnu.org/ml/gcc/2005-03/msg00491.html

I think that the switch name
-fkeep-static-consts might be more consistenly named if it
was given the opposite sense and named something like
-fdelete-unused-static-consts.  The idea here is that by
asserting the switch a particular optimization is _enabled_.
Thus the optimizations performed at each level can be consistently
enumerated by asserting a particular set of switches which enable
specific optimizations.  This would change the present user interface,
however, I doubt that anyone is making extensive use of the current
interface because at present only -fno-keep-static-consts, asserted
at -O0 (no optimization), actually changes the default behavior of
the compiler.
Comment 7 Gary Funck 2005-06-20 23:40:49 UTC
I guess that tagging the bug with a "documentation" keyword doesn't 
necessarily say that the bug is being classified only as a defect in the 
documentation.  However, if that is the meaning of this keyword, then I'd like 
to clarify the bug report.

- yes, the documentation, source code commments and -help are either 
incomplete or do not accurately describe present behavior.

- -fkepp-static-consts behaves in an unexpected manner, in that when asserted, 
it enables a behavior that is already enabled by default.  And interestingly, 
it has no effect when optimization is enabled.

- Only -fno-keep-static-consts has an effect, and then only when optimization 
is not enabled.

- In general, I think it would be best if switches which selectively control 
optimizations, enable that optimization when asserted, and disable the 
optimization when negatively asserted (ie, when prefixed with no- ...).  Thus 
I recommend that -fkeep-static-consts be deprecated, and replaced by a new 
switch, named something like -fdelete-unused-static-consts.  It would also be 
a good idea to look at the other optimization enabling switches to ensure that 
they follow this convention.  Ideally, each optimization level such as O1, O2, 
O3, Os, and Ot would be definitively and completely expressed by the selective 
optimization options they enable.
Comment 8 Manuel López-Ibáñez 2007-11-14 03:05:48 UTC
(In reply to comment #7)
> - yes, the documentation, source code commments and -help are either 
> incomplete or do not accurately describe present behavior.

Confirmed. Patches are welcome.

> - -fkepp-static-consts behaves in an unexpected manner, in that when asserted, 
> it enables a behavior that is already enabled by default.  And interestingly, 
> it has no effect when optimization is enabled.

I would argue that it will make sense that -fkeep-static-consts keeps static consts variables independently of whatever other flags. Then, we could say that it is enabled by default at -O0 and needs to be specifically enabled at higher levels.

> - Only -fno-keep-static-consts has an effect, and then only when optimization 
> is not enabled.

-fno-keep-static-consts should have the effect of disabling -fkeep-static-consts, either because it was enabled by default (at -O0) or because it appeared earlier in the command-line.

> - In general, I think it would be best if switches which selectively control 
> optimizations, enable that optimization when asserted, and disable the 
> optimization when negatively asserted (ie, when prefixed with no- ...).  Thus 
> I recommend that -fkeep-static-consts be deprecated, and replaced by a new 
> switch, named something like -fdelete-unused-static-consts.  It would also be 

That sounds good, but deprecating bad names in released versions is bad. The option is there and there are not many bug reports like these, so it doesn't seem to be so problematic. Let's fix the above problems first.

> a good idea to look at the other optimization enabling switches to ensure that 
> they follow this convention.  Ideally, each optimization level such as O1, O2, 
> O3, Os, and Ot would be definitively and completely expressed by the selective 
> optimization options they enable.

Ot? What is that level supposed to do? Ideally, that sounds good. In practice, there are too many and too diverse optimizations to warrant particular flags.
Comment 9 Hans Ecke 2008-06-23 18:03:17 UTC
FWIW-

I ran into this "bug" too, in the same usecase as Gary. I think the current behavior is close to useless and should be changed as outlined above.

Cheers

Hans
Comment 10 Oleg Goldshmidt 2011-10-21 20:41:51 UTC
Hi,

I recently was bitten by the same "feature" and I would like to add a few points (important, IMHO) to the discussion.

1. I noticed that combining -g with -O2 kept unused static constants in the object files up to version 4.4, but not in 4.5 or 4.6. My tests were all done on Red Hat Linux systems (RHEL or Fedora) rather than on vanilla gcc - I doubt it matters but I think it needs to be mentioned.   

2. I must state that from my prospective the current behaviour is a problem. There is an optimization that cannot be turned off selectively, even as many other optimizations can. The behavior of -fkeep-static-consts is illogical, as others have mentioned. 

3. The use case of version control keywords is a very important one. This thread http://gcc.gnu.org/ml/gcc/2005-04/msg01429.html shows that it is not regarded as such by the GCC team. I do not intend to start a discussion here, but with all due respect there are lots of very practical considerations that may be irrelevant for GCC itself but very relevant in other contexts. I will only make a general statement as follows:

4. GCC optimizes unused static consts away as it understands that they cannot be accessed by any program of which the const is a part. It misses the possibility that the resulting object may be input to another program (e.g., ident(1) or strings(1)) and thus there may be a legitimate reason to keep the const even as other optimizations are applied.

5. I can only regard __attribute__((unused)) as a very poor workaround because it makes the code non-portable and requires, apart from the definition of the constant, at least some preprocessor trickery like #ifdef __GNUC__ / #else / #endif. Dealing with the issue with a compiler option is much better.

This begs for being patched, probably along the lines of what Gary Funck suggested. I may be willing to look at the code and submit such a patch, but I would first appreciate a bit of procedural guidance from developers.

This bug, albeit still NEW and unassigned, is against a very old version. Should a new bug be opened and tracked? 

Given that a patch would change the default behaviour of an option, and the documented "we don't really understand the need for this" opinion (highly respected but contested), is there a reasonable chance that a patch would be accepted?

Has a patch like this been submitted and rejected in the past? Verifying it "from outside" seems a non-trivial task by itself.

Manuel (comment #8)? Anyone? I'd appreciate a reaction before diving in.

Thanks, Oleg.
Comment 11 Pablo Alvarez 2013-11-05 21:18:40 UTC
I was just bitten by this bug myself when upgrading to gcc-4.6. The symptom was exactly the same as Oleg describes:

-g -O2 kept the constants under gcc-4.1
-g -O2 removes the constants under gcc-4.6

This has been a problem for the users of the library I maintain, and I agree with previous posters (Gary, Oleg, etc...) that a fix would be very welcome. Could we have a comment from the gcc team as to whether a patch would be welcome?

Best regards