[OT] compiler optimisations

John Colvin via Digitalmars-d digitalmars-d at puremagic.com
Thu Apr 23 02:14:40 PDT 2015


On Thursday, 23 April 2015 at 08:56:38 UTC, rumbu wrote:
> On Thursday, 23 April 2015 at 08:33:56 UTC, John Colvin wrote:
>> Why can no compiler I try optimise this toy example as I would 
>> expect?
>>
>> // uncomment if using a C compiler
>> // typedef unsigned int uint;
>> uint foo(uint a)
>> {
>>  if (a < 5)
>>    return (a * 3) / 3;
>>  else
>>    return 0;
>> }
>>
>> So, I would expect the compiler to be able to see that it is 
>> equivalent to
>>
>> uint foo(uint a)
>> {
>>  return (a < 5) ? a : 0;
>> }
>>
>> But apparently not a single modern compiler I tried can do 
>> this optimisation, unless it's hidden in some obscure flag I'm 
>> not aware of.
>>
>
> I think because of the potential overflow in a * 3 (if we 
> ignore the a < 5 condition). To optimize this, a compiler must 
> figure out that there is no overflow for any a < 5.
>
> If you change the condition to a > 5 and call foo(uint.max), 
> the two expression above are not equivalent.
>
> int foo(uint a)
> {
> 	if (a > 5)
> 		return (a * 3) / 3;
> 	else
> 		return 0;
> }
>
> int foo_optimized(uint a)
> {
> 	return (a > 5) ? a : 0;
> }
>
> assert(foo(uint.max) == foo_optimized(uint.max)) // -> fail.

Yes, the three things making * and / not inverses of each other 
on unsigned integer types are:

truncation of integer division
div by 0
overflow

But it still amazes me that the compiler can't use the a < 5 
condition here. I regularly watch compilers do what appear to be 
magical transformations and simplifications to my code, but here 
they are tripping up on some very simple maths.


More information about the Digitalmars-d mailing list