Optimisations and undefined behaviour
David Brown
david.brown@hesbynett.no
Sun Nov 8 19:27:00 GMT 2015
On 08/11/15 18:17, Vincent Lefevre wrote:
> On 2015-11-08 16:14:56 +0100, David Brown wrote:
>> I got close with a dont_care() :
>>
>> static inline int dont_care(void) {
>> int x;
>> asm ("" : "=r" (x) : );
>> return x;
>> }
>>
>> This lets gcc "generate" an int without any instructions. But the compiler
>> doesn't know that you don't care what value it has, so this won't let the
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> compiler eliminate the conditional in :
>>
>> int foo(int x) {
>> if (x < 1000) {
>> return x * x * x;
>> } else {
>> return dont_care();
>> }
>> }
>
> I don't think that this is the problem here. First, the conditional
> could be eliminated only if the code is in the x < 1000 case does not
> have side effects (such as traps in case of overflow). Moreover, even
> if the compiler knows that it is safe to do the transformation, would
> it know that doing it would yield faster code? This is not obvious.
>
The compiler knows that the code in the "x * x * x" branch is without
side-effects or traps. It also knows that omitting the conditional
leads to smaller and faster code. But what it does not know, is if the
/asm/ instruction has side effects or not. That, I think, is why the
comparison is kept.
> IMHO, the right thing to do is to have a way to instruct the compiler
> that the multiplication has some defined behavior even in case of
> overflow. Something like -fwrapv. However, the problems with -fwrapv
> is that it is not part of the semantic of the code and that it is
> global.
That would not help, as it is not the behaviour of the integer
multiplication that matters. (Changing to unsigned int, which has no
undefined behaviour on overflow, does not make a difference.)
>
>> Another option is:
>>
>> static inline int dont_care2(void) {
>> int x = x;
>> return x;
>> }
>>
>> But that sometimes ends up with an unnecessary setting of x to 0.
>
> And this is also undefined behavior.
>
You are correct as far as I can see. gcc (and many other compilers) can
accept this syntax as a way of avoiding warnings about data that might
be used uninitialised, but actually /using/ the self-initialised
variable is undefined behaviour, I think.
So I am still searching for an unspecified, but not undefined, int
generator.
More information about the Gcc-help
mailing list