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 

More information about the Gcc-help mailing list