Hello, all,
I have doubts about asm generated for the following code that performs
orientation test for a point and a segment:
double orient_test_2d(const double m[2], const double a[2], const double
b[2])
{
double am1 = a[0]-m[0];
double bm1 = b[1]-m[1];
double am2 = a[1]-m[1];
double bm2 = b[0]-m[0];
return ((am1)*(bm1)) - ((am2)*(bm2));
}
In the return statement the operands are all in parentheses. gcc
optimizes the statement and introduces a FMA instruction. I think this
is wrong because FMA causes the subtraction and multiplication to be
effectively executed at the same time, while the source specifies that
the multiplications should be performed before the subtraction.
This is the assembly generated by 'gcc-5.1.0 -O3 -mfma test.c -c -S'
.cfi_startproc
vmovsd 8(%rdi), %xmm0
vmovsd 8(%rsi), %xmm2
vmovsd (%rdi), %xmm1
vsubsd %xmm0, %xmm2, %xmm3
vmovsd (%rdx), %xmm2
vsubsd %xmm1, %xmm2, %xmm2
vmulsd %xmm2, %xmm3, %xmm2
vmovsd (%rsi), %xmm3
vsubsd %xmm1, %xmm3, %xmm3
vmovsd 8(%rdx), %xmm1
vsubsd %xmm0, %xmm1, %xmm1
vfmsub132sd %xmm1, %xmm2, %xmm3
vmovapd %xmm3, %xmm0
ret
.cfi_endproc
I believe that in order to honor the parentheses gcc should NOT generate
the FMA, but stick to the programmed operation order. If I wanted a FMA,
I would not use parentheses around the multiplications. Current behavior
of gcc results in inconsistent behavior in my code due to floating point
arithmetic errors.
As a side note, the Intel compiler does exactly the same thing.
Can this be considered a bug, or is this the expected behavior? If this
is ok, how can I assure in a portable way the effect that I need?
Thanks!
Marcin Krotkiewski