On 10/02/2017 04:40 AM, Jakub Jelinek wrote:
On Mon, Oct 02, 2017 at 09:05:06PM +1030, Alan Modra wrote:
and taking different paths depending on whether or not the test
succeeds.
As far as can see, the tests have been there since the pass was
added, but I don't understand from the comments in the file what
their purpose is or why optimization decisions involving one set
of functions (I think strcpy and strcat at a minimum) are based
on whether another function has been declared or not.
Can you explain what they're for?
The reason is that stpcpy is not a standard C function, so in non-POSIX
environments one could have stpcpy with completely unrelated prototype
used for something else. In such case we don't want to introduce stpcpy
into a TU that didn't have such a call. So, we use the existence of
a matching prototype as a sign that stpcpy can be synthetized.
Why is the test for stpcpy being declared done for the strcpy cases
rather than the stpcpy cases?
Because the optimization is about strcpy followed by some call that would
like to know the length of the string, so we want to replace the strcpy call
by stpcpy and use the lhs of the stpcpy call - the first argument as the
length instead of yet another strlen call (or similar).
If we don't know that stpcpy is available and can be safely used, we can't
do that.
The reason why a matching prototype is sufficient is that if you have a
matching prototype (and no -fno-builtin-stpcpy or -fno-builtin) and have
calls to that function in your code, GCC considers it a builtin and
optimizes them according to the behavior of the builtin.
Thanks. That makes sense to me. The wrinkle with this approach
is that the same code (same function) has different effects on
the compiler (as in, is subject to different optimization
decisions, or can cause false positives/negatives) depending
whether some unrelated code (in another function) calls
__builtin_stpcpy or calls (and declares) stpcpy, or does neither.
This is probably not very common in application programs but it
does happen often in the GCC test suite (this is the second time
I've been bitten by it in just a few months).
IIUC, ideally, the decision whether or not to make
the transformation would be based on whether stpcpy is called
by the function on the result of a prior strcpy/strcat. A less
ideal solution, but probably a good enough one to avoid the kind
of surprises I ran into, would only check whether stpcpy is called
by each function. Is there a way to do either without making
overly intrusive changes to the pass? It seems the latter should
be doable simply by scanning each function for calls to stpcpy
first, either by the strlen pass itself or by some earlier pass.
Or is there something I'm missing that makes this not feasible?
Martin