Fix complex arithmetic and signed zeros

H.J. Lu hjl.tools@gmail.com
Sat Jan 1 23:01:00 GMT 2011


On Thu, May 7, 2009 at 11:27 AM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> This patch implements the C99 requirements that arithmetic between one
> real and one complex operand does not convert the real operand to a
> complex type.  This avoids excess operations on zero values in such
> cases, which are inefficient and can lead to the wrong sign of zero in
> the result (recall that positive and negative zero add to positive
> zero in all rounding modes except towards negative infinity).  There
> appear to be no specific requirements regarding the result of
> real/complex division that make converting both operands to a common
> complex type there wrong, and that case might also need a new libgcc
> function or other special handling to avoid the conversion, so nothing
> is done about that case.
>
> There is some code in tree-complex.c that tries to optimize complex
> arithmetic with one operand real or imaginary, but if there are two
> complex operands then that is different from the case of one real and
> one complex operand because of the handling of signed zeros.  Thus
> this must be disabled if flag_signed_zeros to get the correct
> semantics.
>
> Note that the absence of imaginary types means that expressions of the
> form (a + b * I) may still yield unwanted results in some cases
> because of b * I being b * (0.0 + 1.0i).  As far as I know this
> (signed zeros in complex numbers) is the only use of imaginary types,
> and they are not a generally implemented feature of C99 (Annex G is an
> informative Annex, not normative; the Power ABI working group did not
> find any sign of compilers for Power Architecture that implemented
> these types).  So I do not propose to change anything regarding their
> unimplemented state in GCC.
>
> I believe the only piece needed after this patch to make complex
> numbers support Done in c99status.html is fixing complex arithmetic
> folding (PR 30789), likely using MPC.
>
> Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  OK to
> commit (the tree-complex.c part)?
>
> The C front-end code checks flag_signed_zeros because it appears the
> language-independent compiler is better with -fno-signed-zeros at
> optimizing the complex arithmetic than at optimizing the accurately
> represented real/complex arithmetic.  Without that check,
> gcc.dg/builtins-20.c, gcc.dg/builtins-54.c and gcc.dg/pr30172-1.c fail
> (the last is checking an early GIMPLE dump before most optimizations,
> but the first two do suggest a real problem).  The complicated ENCODE
> code in the testcases is because if you initialize both halves of a
> complex number using __real__ and __imag__ assignments (the simplest
> way of putting known values, including signed zeros, in both halves),
> the compiler hasn't worked out that the complex number has a constant
> value by the time it gets to lowering complex arithmetic, so tests
> using __real__ and __imag__ assignments wouldn't detect the
> problematic transformations for complex numbers with one part zero.
>
> 2009-05-07  Joseph Myers  <joseph@codesourcery.com>
>
>        PR c/24581
>        * c-typeck.c (build_binary_op): Handle arithmetic between one real
>        and one complex operand specially.
>        * tree-complex.c (some_nonzerop): Do not identify a real value as
>        zero if flag_signed_zeros.
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47150


H.J.



More information about the Gcc-patches mailing list