On Wed, 6 Dec 2000, Patrik Stridvall wrote:
> > > > The compiler is also *expected* to
> > > > remove dead code,
> > > > *especially* if attribute((unused)) is used, as this
> > attribute is very
> > > > often used in inline functions in .h files.
> > >
> > > OK perhaps "attribute((unused))" does something differently that I
> > > orginally thought. However the optimizer can check for inline
> > > attribute as well can't it?
> >
> > Sure - and if absent, optimization levels -O3 (and above)
> > decides on its
> > own whether to inline the function or not. This is desired
> > behaviour, old
> > & portable C code isn't written with "inline" all over it, it's the
> > compiler's job to optimize where it can.
>
> Yes, but old portable code doesn't use __attribute__((unused)) does it?
Someone may want to use a #ifdef __GNUC__ #define UNUSED
__attribute__((unused)) #else #defined UNUSED #endif in portable code to
suppress warnings for a particular inline function. I don't see problems
with that. Better than using pragmas, too.
> In any case, ask yourself whether you prefer you old & portable
> application to work correctly or whether you want it to possibly
> have subtle bugs. Better safe that sorry IMHO.
Why should I need to ask? gcc *doesn't* have such a bug, it will not
generate incorrect code for portable applications just because you become
confused by ill-defined unportable code.
> > > What ever is
> > > static void init(void) __attribute__((unused));
> > > supposed to mean absent any implementation?
> >
> > That it's a prototype, obviously.
>
> Indeed, a prototype for something the compiler might not
> be able to detect and therefore avoid to warn about
> and/or remove during optimization.
Yes, that it's free to remove its implementation without warning if it's
not used. The "static" qualifier says that it'll not be used anywhere
outside the compilation unit, so it doesn't have to emit any code for it
unless necessary, and the "unused" attribute says that it may not even be
used, e.g. if the function is in a .h file, or the code using it is inside
an #ifdef.
> > It's even one that has the potential to demand
> > multipassing, which the
> > C standard is written to avoid the need for by allowing prototypes,
> > attributes, incomplete types, etc... and now you want to
> > invalidate all
> > this effort to make C a fast single-pass compiler language.
>
> How do you perform dead function removal without multiple passes?
Well, gcc doesn't. What happens is that gcc compiles one function at a
time, then sends the result to the assembler before proceeding to the next
function, I don't think it goes back to recompile earlier functions. But a
function can be compiled into an inline definition (in which case "static"
says it doesn't have to emit an actual function) if it seems simple enough
(or "inline" is specified explicitly). It can then be embedded into
functions that call this inlined function. (And if the function is
referenced by address somewhere, then I suppose the compiler can decide to
dump the inlined definition out to the assembler as a real function at
that point - but even if that happens, it doesn't exclude continuing to
inline the function where it's just called directly.)
This works just fine with a single pass through the code, even managing to
completely remove unused functions if they are eligible for inlining.
> > But the "init" implementation does exist, the compiler just decides to
> > inline it.
>
> Yes, ignoring the __attribute__((unused)) constraint,
How many times do I have to tell you, it's not a constraint!
> which should mean IMHO in absence of explict inline
> do not ever inline it (see below).
Now you're back to wanting to have heuristics in the compiler, having it
second-guessing what the programmer wants to happen when the programmer is
using an attribute that has completely unrelated semantics. I don't want
the unpredictable (MS-like) compiler you're proposing, I don't want a
compiler that uses heuristics to determine what the programmer wants
(heuristics should be limited to what can be optimized, which is perfectly
okay, since that can never generate incorrect code). Each attribute should
have well-defined semantics, and combinations of them should have the
expected effect of combining them, not having a completely different
effect because of your idea of letting a compiler second-guess what the
programmer wants by a particular combination or lack of combination of
unrelated attributes.
static has a well-defined meaning - not available outside the module
inline has a well-defined meaning - inlining a function
-O3 has a well-defined semantic - automatically add "inline" all over
attribute((unused)) has a well-defined meaning - no "unused" warnings
I don't want mixing these to mean something else than mixing these! A
compiler that changes the meaning of mixing attributes by assuming things
the programmer didn't say is going to create a *lot* of confusion. Sure,
maybe the compiler will be more "user-friendly" for people like you, but
since when was user-friendliness more important than predictable
compilers?
> > > Regardless the fact remains _if_ -O6 uses _heuristics_ (see
> > below) it
> > > might generate wrong code even if it is bug free. Note _if_.
> >
> > It does use heuristics to determine whether to inline the
> > function or not,
> > and it will never generate wrong code. Again, what's so hard
> > to understand
> > about that?
>
> I think we have different definitions of heuristics.
So, you ignore the definition of heuristics the documentation uses, apply
your own definition instead, add some weird assumptions in order to reach
a conclusion, then use the result as an implicit argument against my
reasoning. How enlightening.
> > For
> > example, the most important heuristic the compiler employs is that the
> > function simply cannot be inlined if it's referenced by
> > address, rather
> > than just called, or if it's calling itself recursively.
>
> But that is not an heuristic. If it it referenced or recusive
> it is always correct to not inline it.
Yeah, so the heuristic can perform well in those cases.
> There is no incorrect cases and therefore it is not an heuristic it is
> an algoritm and i'm not possitive that it is even a non-optimal
> algoritm.
Algorithm? It's using rules, not algorithms. That's what heuristics are,
even according to this dictionary. And there are certainly incorrect cases
when the goal is a perfectly optimized program - the optimizer can choose
a suboptimal path, which is the wrong path to perfect optimization.
> Sure but you will if you incorrectly eliminate dead code
> that is the case now.
Dead code is dead code and can never be eliminated incorrectly, since it's
dead and not used by definition. A C program will never become incorrect
because of this (this is an assembler problem), and removing this feature
will certainly cause an outcry and probably much bigger Linux
distributions...
> The key word is unconstrained, which is the point where I don't agree.
What you agree to is inconsequential - the compiler and its language
definition is the "absolute truth", opinions on what it does and the
semantics of a piece of code are meaningless, it is unambiguously defined,
not subject to compromise or interpretation.
> > > Sure, any bug can be documented and become a feature.
> > > Microsoft is an expert on this. :-)
> >
> > And you're becoming an expert on attacking well-designed features and
> > calling them bugs just because you don't like them, or like any
> > prejudicial person, fear them because you don't understand them.
>
> I certainly don't like the way it works now,
> but that doesn't nessary make me prejudical,
> does it?
Well, you call it a bug that it doesn't conform to your ideals of
user-friendliness, which is either prejudicial or FUD, and I didn't think
you wanted to FUD gcc.
> > Undefined when not handled by the heuristics? If you can't
> > stop writing
> > long essays abouts things you've misunderstood, are you sure
> > you're fit to
> > be a hacker?
>
> Aren't you becoming a little personal now?
Yes, but when I'm tired of your constantly low signal/noise ratio in all
the discussions I've seen you in up to now, I feel it must soon be time
for you to readjust your argumentation techniques and ability of digesting
external arguments, in order to reduce your tendency of argument
redundancy and recycling already refuted arguments. It's not fun to be
objective with someone who has a problem with objective refutation, and I
want you to start becoming productive rather than writing two tons of
paperwork nobody is going to buy every time someone speaks up against
something you said.
> Yes, constraints like __attribute__((unused)).
That's not a constraint.
> Then we have a little missundering with the word heurstics.
> There are four kinds of algoritms.
>
> 1. Optimal algoritms
> 2. Non-optimal algoritms
> 3 Algoritms buggy by design
> 4. Algoritms buggy by misstake
>
> As far as I'm concern 3 is heuristics,
> but you seem to wish to include 2 as well.
I don't have to. For one, your definitions isn't complete - optimal can
refer to the efficiency of the algorithm, or the efficiency of the result.
And second, a heuristic is the antonym of an algorithm.
But you seem to constantly mix the question of optimization and code
correctness, which are quite orthogonal and independent issues. The
heuristic applies to "how to optimize this?" If the heuristic chooses a
non-optimal (wrong) optimization, it's a bug in it, yet the code
generation is not affected - it will still produce working and correct
code, the code generation stage is deterministic and doesn't use
heuristics itself, just input from the previous stages telling it what
techniques makes sense to use.
> > Which constraints? Our code doesn't contain any constraints
> > at all, that's
> > the problem. If you tell the gcc people that they have a bug
> > because Wine
> > code is using gcc extensions (asm) incorrectly, I'm sure
> > they'll have a
> > good laugh on your expense...
>
> But it isn't, it is using the _ANSI_ C feature asm which
> doesn't have any constraints. There is a difference between
> not specifing any constraints and specifing that there is
> no constraints you know.
Not really. So, does ANSI C state that what gcc does is illegal? Hmm... I
have some doubts.
> >From the gcc manual.
> < `unused'
> < This attribute, attached to a function, means that the function is
> < meant to be possibly unused. GNU CC will not produce a warning
> < for this function.
>
> It says that no warning will be issued and it is _possibly_ unused.
> Note _possibly_.
Of course! Why would anyone bother to write a function that they knew
would absolutely certainly *never* be used?!
> I interpret this as a definition _might_ exists
> somewhere but if the compiler can't detect it, it shouldn't produce
> a warning.
Definition? What does a *definition* have to do with *usage*? It doesn't
emit a warning (where it would normally if the function is static) if the
function is never *used*, which means "called" or "referenced".
> Your interpretation that it should agresively optimize it away
> if it can't detect it.
Not really, gcc will decide on that independently of this attribute, but
with this attribute, it won't produce a warning about the function. It'd
just make sense that this attribute would increase the likelihood that the
function is removed (inlined), but the optimizer doesn't need to take that
into account since it already does that otherwise. This attribute is most
useful in .h files.
> This is IMHO inconsistant with _possibly_
> unused.
Perfectly consistent. If it's unused, take it away without warning, if
it's used, leave it there. Nice for static functions in .h files.
> In the mail I sent later in the night that you haven't answer (yet),
Should I? No sense in increasing the number of mails here, when I already
took it into account in the mail you replied to here.
> I try very briefly to explain that what you want to happend can
> be done with other means that doesn't involve having
> the optimizer hope and pray that nobody uses it.
Saw no such thing. The only thing I could see is that you kept mistakenly
calling it a bug in the compiler that absolutely must be fixed by changing
the attribute semantics to conform with your view of the world instead of
the way it is documented and probably used everywhere by now. Not many is
going to be happy about that.
> If the constraint __attribute__((unused)) doesn't exist I
> agree that is correct to remove because then you haven't
> said anything about the function neither in any
> asm constraint nor in any other constraint.
It's still not a constraint, and the "unused" attribute is *particularly*
used (and meant to be used) when it's correct to remove the function.
Don't try to pretend otherwise, it won't work.
> In short, I expect GNU C to do the following:
[...]
Go ahead, make the gcc-developers' day. I expect to hear the laughter over
here soon.
All you can hope for, is to add a new attribute that actually *has*
relevant semantics, like __attribute__((noinline)), if it doesn't already
exist.
> Is this really so stupid, that you have to resort to
> name calling during the argument?
Yes.