On Thursday, 23 April 2015 at 12:37:12 UTC, Ola Fosheim Grøstad
wrote:
On Thursday, 23 April 2015 at 08:56:38 UTC, rumbu wrote:
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.
Yes, it is because of modular artithmetics which is a D design
flaw. In C++ this only applies to unsigned integers, signed
integers are monothonic in C++. I think Rust uses non-modular
for both and Ada allows you to specify it.
Compiled using ICC:
int foo(int a)
{
if (a > 5)
return (a * 3) / 3;
else
return 0;
}
yields:
xorl %edx, %edx
cmpl $5, %edi
cmovle %edx, %edi
movl %edi, %eax
ret
---------------------------------
int foo(unsigned int a)
{
if (a > 5)
return (a * 3) / 3;
else
return 0;
}
yields:
cmpl $5, %edi
jbe ..B1.3
movl $-1431655765, %eax
lea (%rdi,%rdi,2), %ecx
mull %ecx
shrl $1, %edx
movl %edx, %eax
ret
..B1.3:
xorl %eax, %eax
ret
Just to confirm this, all C compilers I tried were able to use
the undefined behaviour of signed overflow to avoid the
multiplication. D compilers of course do not do this, as signed
overflow is defined.
Nonetheless, I maintain that the compiler should be able to
propagate the value range of a and perform the optimisation
regardless.