re PR c/24581 (Complex arithmetic on special cases is incorrect.)

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.

testsuite:
	* gcc.dg/torture/complex-sign.h: New header.
	* gcc.dg/torture/complex-sign-add.c,
	gcc.dg/torture/complex-sign-mixed-add.c,
	gcc.dg/torture/complex-sign-mixed-div.c,
	gcc.dg/torture/complex-sign-mixed-mul.c,
	gcc.dg/torture/complex-sign-mixed-sub.c,
	gcc.dg/torture/complex-sign-mul.c,
	gcc.dg/torture/complex-sign-sub.c: New tests.

From-SVN: r147281
This commit is contained in:
Joseph Myers 2009-05-08 11:22:08 +01:00 committed by Joseph Myers
parent cb8e4445ef
commit 2ca862e9dd
12 changed files with 547 additions and 2 deletions

View File

@ -1,3 +1,11 @@
2009-05-08 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.
2009-05-08 Paolo Bonzini <bonzini@gnu.org>
PR rtl-optimization/33928

View File

@ -9246,7 +9246,9 @@ build_binary_op (location_t location, enum tree_code code,
(code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
|| code1 == FIXED_POINT_TYPE || code1 == VECTOR_TYPE))
{
int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
bool first_complex = (code0 == COMPLEX_TYPE);
bool second_complex = (code1 == COMPLEX_TYPE);
int none_complex = (!first_complex && !second_complex);
if (shorten || common || short_compare)
{
@ -9255,6 +9257,89 @@ build_binary_op (location_t location, enum tree_code code,
return error_mark_node;
}
if (first_complex != second_complex
&& (code == PLUS_EXPR
|| code == MINUS_EXPR
|| code == MULT_EXPR
|| (code == TRUNC_DIV_EXPR && first_complex))
&& TREE_CODE (TREE_TYPE (result_type)) == REAL_TYPE
&& flag_signed_zeros)
{
/* An operation on mixed real/complex operands must be
handled specially, but the language-independent code can
more easily optimize the plain complex arithmetic if
-fno-signed-zeros. */
tree real_type = TREE_TYPE (result_type);
tree real, imag;
if (type0 != orig_type0 || type1 != orig_type1)
{
gcc_assert (may_need_excess_precision && common);
real_result_type = c_common_type (orig_type0, orig_type1);
}
if (first_complex)
{
if (TREE_TYPE (op0) != result_type)
op0 = convert_and_check (result_type, op0);
if (TREE_TYPE (op1) != real_type)
op1 = convert_and_check (real_type, op1);
}
else
{
if (TREE_TYPE (op0) != real_type)
op0 = convert_and_check (real_type, op0);
if (TREE_TYPE (op1) != result_type)
op1 = convert_and_check (result_type, op1);
}
if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
return error_mark_node;
if (first_complex)
{
op0 = c_save_expr (op0);
real = build_unary_op (EXPR_LOCATION (orig_op0), REALPART_EXPR,
op0, 1);
imag = build_unary_op (EXPR_LOCATION (orig_op0), IMAGPART_EXPR,
op0, 1);
switch (code)
{
case MULT_EXPR:
case TRUNC_DIV_EXPR:
imag = build2 (resultcode, real_type, imag, op1);
/* Fall through. */
case PLUS_EXPR:
case MINUS_EXPR:
real = build2 (resultcode, real_type, real, op1);
break;
default:
gcc_unreachable();
}
}
else
{
op1 = c_save_expr (op1);
real = build_unary_op (EXPR_LOCATION (orig_op1), REALPART_EXPR,
op1, 1);
imag = build_unary_op (EXPR_LOCATION (orig_op1), IMAGPART_EXPR,
op1, 1);
switch (code)
{
case MULT_EXPR:
imag = build2 (resultcode, real_type, op0, imag);
/* Fall through. */
case PLUS_EXPR:
real = build2 (resultcode, real_type, op0, real);
break;
case MINUS_EXPR:
real = build2 (resultcode, real_type, op0, real);
imag = build1 (NEGATE_EXPR, real_type, imag);
break;
default:
gcc_unreachable();
}
}
ret = build2 (COMPLEX_EXPR, result_type, real, imag);
goto return_build_binary_op;
}
/* For certain operations (which identify themselves by shorten != 0)
if both args were extended from the same smaller type,
do the arithmetic in that type and then extend.

View File

@ -1,3 +1,15 @@
2009-05-08 Joseph Myers <joseph@codesourcery.com>
PR c/24581
* gcc.dg/torture/complex-sign.h: New header.
* gcc.dg/torture/complex-sign-add.c,
gcc.dg/torture/complex-sign-mixed-add.c,
gcc.dg/torture/complex-sign-mixed-div.c,
gcc.dg/torture/complex-sign-mixed-mul.c,
gcc.dg/torture/complex-sign-mixed-sub.c,
gcc.dg/torture/complex-sign-mul.c,
gcc.dg/torture/complex-sign-sub.c: New tests.
2009-05-08 Janus Weil <janus@gcc.gnu.org>
PR fortran/39876

View File

@ -0,0 +1,53 @@
/* Test complex arithmetic with signed zeros. Pure complex
addition. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
#include "complex-sign.h"
#define CHECK_ADD(TYPE, COPY, ZERO, ZEROI) \
do { \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, +, +, +, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, +, +, +, -, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, +, +, -, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, +, +, -, -, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, +, -, +, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, +, -, +, -, +, -); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, +, -, -, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, +, -, -, -, +, -); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, -, +, +, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, -, +, +, -, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, -, +, -, +, -, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, -, +, -, -, -, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, -, -, +, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, -, -, +, -, +, -); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, -, -, -, +, -, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, +, -, -, -, -, -, -); \
} while (0)
void
check_add_float (void)
{
CHECK_ADD (float, __builtin_copysignf, 0.0f, 0.0if);
}
void
check_add_double (void)
{
CHECK_ADD (double, __builtin_copysign, 0.0, 0.0i);
}
void
check_add_long_double (void)
{
CHECK_ADD (long double, __builtin_copysignl, 0.0l, 0.0il);
}
int
main (void)
{
check_add_float ();
check_add_double ();
check_add_long_double ();
exit (0);
}

View File

@ -0,0 +1,53 @@
/* Test complex arithmetic with signed zeros. Mixed real/complex
addition. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
#include "complex-sign.h"
#define CHECK_ADD(TYPE, COPY, ZERO, ZEROI) \
do { \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, +, +, +, +, +, +); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, +, +, +, -, +, -); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, +, +, -, +, +, +); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, +, +, -, -, +, -); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, +, -, +, +, +, +); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, +, -, +, -, +, -); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, +, -, -, +, -, +); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, +, -, -, -, -, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, +, +, +, +, ZERO, +, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, +, +, +, -, ZERO, +, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, +, +, -, +, ZERO, +, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, +, +, -, -, ZERO, +, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, +, -, +, +, ZERO, +, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, +, -, +, -, ZERO, -, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, +, -, -, +, ZERO, +, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, +, -, -, -, ZERO, -, -); \
} while (0)
void
check_add_float (void)
{
CHECK_ADD (float, __builtin_copysignf, 0.0f, 0.0if);
}
void
check_add_double (void)
{
CHECK_ADD (double, __builtin_copysign, 0.0, 0.0i);
}
void
check_add_long_double (void)
{
CHECK_ADD (long double, __builtin_copysignl, 0.0l, 0.0il);
}
int
main (void)
{
check_add_float ();
check_add_double ();
check_add_long_double ();
exit (0);
}

View File

@ -0,0 +1,45 @@
/* Test complex arithmetic with signed zeros. Mixed real/complex
division. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
#include "complex-sign.h"
#define CHECK_DIV(TYPE, COPY, ZERO, ZEROI, ONE) \
do { \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, /, +, +, +, ONE, +, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, /, +, +, -, ONE, -, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, /, +, -, +, ONE, +, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, /, +, -, -, ONE, -, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, /, -, +, +, ONE, -, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, /, -, +, -, ONE, +, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, /, -, -, +, ONE, -, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, /, -, -, -, ONE, +, +); \
} while (0)
void
check_div_float (void)
{
CHECK_DIV (float, __builtin_copysignf, 0.0f, 0.0if, 1.0f);
}
void
check_div_double (void)
{
CHECK_DIV (double, __builtin_copysign, 0.0, 0.0i, 1.0);
}
void
check_div_long_double (void)
{
CHECK_DIV (long double, __builtin_copysignl, 0.0l, 0.0il, 1.0l);
}
int
main (void)
{
check_div_float ();
check_div_double ();
check_div_long_double ();
exit (0);
}

View File

@ -0,0 +1,53 @@
/* Test complex arithmetic with signed zeros. Mixed real/complex
multiplication. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
#include "complex-sign.h"
#define CHECK_MUL(TYPE, COPY, ZERO, ZEROI) \
do { \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, *, +, +, +, +, +); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, *, +, +, -, +, -); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, *, +, -, +, -, +); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, *, +, -, -, -, -); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, *, -, +, +, -, -); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, *, -, +, -, -, +); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, *, -, -, +, +, -); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, *, -, -, -, +, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, *, +, +, +, ZERO, +, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, *, +, +, -, ZERO, -, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, *, +, -, +, ZERO, +, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, *, +, -, -, ZERO, -, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, *, -, +, +, ZERO, -, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, *, -, +, -, ZERO, +, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, *, -, -, +, ZERO, -, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, *, -, -, -, ZERO, +, +); \
} while (0)
void
check_mul_float (void)
{
CHECK_MUL (float, __builtin_copysignf, 0.0f, 0.0if);
}
void
check_mul_double (void)
{
CHECK_MUL (double, __builtin_copysign, 0.0, 0.0i);
}
void
check_mul_long_double (void)
{
CHECK_MUL (long double, __builtin_copysignl, 0.0l, 0.0il);
}
int
main (void)
{
check_mul_float ();
check_mul_double ();
check_mul_long_double ();
exit (0);
}

View File

@ -0,0 +1,53 @@
/* Test complex arithmetic with signed zeros. Mixed real/complex
subtraction. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
#include "complex-sign.h"
#define CHECK_SUB(TYPE, COPY, ZERO, ZEROI) \
do { \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, -, +, +, +, +, -); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, -, +, +, -, +, +); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, -, +, -, +, +, -); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, -, +, -, -, +, +); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, -, -, +, +, -, -); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, -, -, +, -, -, +); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, -, -, -, +, +, -); \
CHECK_ARITH_RC (TYPE, COPY, ZERO, ZEROI, -, -, -, -, +, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, -, +, +, +, ZERO, +, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, -, +, +, -, ZERO, +, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, -, +, -, +, ZERO, +, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, -, +, -, -, ZERO, +, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, -, -, +, +, ZERO, -, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, -, -, +, -, ZERO, +, +); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, -, -, -, +, ZERO, -, -); \
CHECK_ARITH_CR (TYPE, COPY, ZERO, ZEROI, -, -, -, -, ZERO, +, -); \
} while (0)
void
check_sub_float (void)
{
CHECK_SUB (float, __builtin_copysignf, 0.0f, 0.0if);
}
void
check_sub_double (void)
{
CHECK_SUB (double, __builtin_copysign, 0.0, 0.0i);
}
void
check_sub_long_double (void)
{
CHECK_SUB (long double, __builtin_copysignl, 0.0l, 0.0il);
}
int
main (void)
{
check_sub_float ();
check_sub_double ();
check_sub_long_double ();
exit (0);
}

View File

@ -0,0 +1,53 @@
/* Test complex arithmetic with signed zeros. Pure complex
multiplication. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
#include "complex-sign.h"
#define CHECK_MUL(TYPE, COPY, ZERO, ZEROI) \
do { \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, +, +, +, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, +, +, +, -, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, +, +, -, +, -, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, +, +, -, -, +, -); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, +, -, +, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, +, -, +, -, +, -); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, +, -, -, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, +, -, -, -, -, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, -, +, +, +, -, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, -, +, +, -, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, -, +, -, +, +, -); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, -, +, -, -, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, -, -, +, +, +, -); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, -, -, +, -, -, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, -, -, -, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, *, -, -, -, -, +, +); \
} while (0)
void
check_mul_float (void)
{
CHECK_MUL (float, __builtin_copysignf, 0.0f, 0.0if);
}
void
check_mul_double (void)
{
CHECK_MUL (double, __builtin_copysign, 0.0, 0.0i);
}
void
check_mul_long_double (void)
{
CHECK_MUL (long double, __builtin_copysignl, 0.0l, 0.0il);
}
int
main (void)
{
check_mul_float ();
check_mul_double ();
check_mul_long_double ();
exit (0);
}

View File

@ -0,0 +1,53 @@
/* Test complex arithmetic with signed zeros. Pure complex
subtraction. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
#include "complex-sign.h"
#define CHECK_SUB(TYPE, COPY, ZERO, ZEROI) \
do { \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, +, +, +, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, +, +, +, -, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, +, +, -, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, +, +, -, -, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, +, -, +, +, +, -); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, +, -, +, -, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, +, -, -, +, +, -); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, +, -, -, -, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, -, +, +, +, -, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, -, +, +, -, -, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, -, +, -, +, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, -, +, -, -, +, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, -, -, +, +, -, -); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, -, -, +, -, -, +); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, -, -, -, +, +, -); \
CHECK_ARITH (TYPE, COPY, ZERO, ZEROI, -, -, -, -, -, +, +); \
} while (0)
void
check_sub_float (void)
{
CHECK_SUB (float, __builtin_copysignf, 0.0f, 0.0if);
}
void
check_sub_double (void)
{
CHECK_SUB (double, __builtin_copysign, 0.0, 0.0i);
}
void
check_sub_long_double (void)
{
CHECK_SUB (long double, __builtin_copysignl, 0.0l, 0.0il);
}
int
main (void)
{
check_sub_float ();
check_sub_double ();
check_sub_long_double ();
exit (0);
}

View File

@ -0,0 +1,74 @@
/* Common header for complex arithmetic sign tests. */
extern void abort (void);
extern void exit (int);
#define CHECK_RES(VALUE, COPY, SIGN_REAL, SIGN_IMAG) \
do { \
if ((VALUE) != 0 \
|| COPY (1.0, __real__ (VALUE)) != SIGN_REAL 1.0 \
|| COPY (1.0, __imag__ (VALUE)) != SIGN_IMAG 1.0) \
abort (); \
} while (0)
/* This definition is intended to work with or without imaginary
types, as long as mixed real/complex arithmetic is handled
correctly. */
#define ENCODE(ZERO, ZEROI, SA, SB) \
(SA 1 == 1 \
? SB 1 == 1 ? ZERO + ZEROI : ZERO - ZEROI \
: SB 1 == 1 ? -(ZERO - ZEROI) : -(ZERO + ZEROI))
#define CHECK_ARITH(TYPE, COPY, ZERO, ZEROI, OP, S1, S2, S3, S4, SR, SI) \
do { \
_Complex TYPE a1, b1, c1; \
volatile _Complex TYPE a2, b2, c2; \
a1 = ENCODE(ZERO, ZEROI, S1, S2); \
CHECK_RES (a1, COPY, S1, S2); \
b1 = ENCODE(ZERO, ZEROI, S3, S4); \
CHECK_RES (b1, COPY, S3, S4); \
c1 = a1 OP b1; \
CHECK_RES (c1, COPY, SR, SI); \
a2 = ENCODE(ZERO, ZEROI, S1, S2); \
CHECK_RES (a2, COPY, S1, S2); \
b2 = ENCODE(ZERO, ZEROI, S3, S4); \
CHECK_RES (b2, COPY, S3, S4); \
c2 = a2 OP b2; \
CHECK_RES (c2, COPY, SR, SI); \
} while (0)
#define CHECK_ARITH_RC(TYPE, COPY, ZERO, ZEROI, OP, S1, S3, S4, SR, SI) \
do { \
TYPE a1; \
_Complex TYPE b1, c1; \
volatile TYPE a2; \
volatile _Complex TYPE b2, c2; \
a1 = S1 ZERO; \
b1 = ENCODE(ZERO, ZEROI, S3, S4); \
CHECK_RES (b1, COPY, S3, S4); \
c1 = a1 OP b1; \
CHECK_RES (c1, COPY, SR, SI); \
a2 = S1 ZERO; \
b2 = ENCODE(ZERO, ZEROI, S3, S4); \
CHECK_RES (b2, COPY, S3, S4); \
c2 = a2 OP b2; \
CHECK_RES (c2, COPY, SR, SI); \
} while (0)
#define CHECK_ARITH_CR(TYPE, COPY, ZERO, ZEROI, OP, S1, S2, S3, V3, SR, SI) \
do { \
_Complex TYPE a1, c1; \
TYPE b1; \
volatile _Complex TYPE a2, c2; \
volatile TYPE b2; \
a1 = ENCODE(ZERO, ZEROI, S1, S2); \
CHECK_RES (a1, COPY, S1, S2); \
b1 = S3 V3; \
c1 = a1 OP b1; \
CHECK_RES (c1, COPY, SR, SI); \
a2 = ENCODE(ZERO, ZEROI, S1, S2); \
CHECK_RES (a2, COPY, S1, S2); \
b2 = S3 V3; \
c2 = a2 OP b2; \
CHECK_RES (c2, COPY, SR, SI); \
} while (0)

View File

@ -99,7 +99,10 @@ some_nonzerop (tree t)
{
int zerop = false;
if (TREE_CODE (t) == REAL_CST)
/* Operations with real or imaginary part of a complex number zero
cannot be treated the same as operations with a real or imaginary
operand if we care about the signs of zeros in the result. */
if (TREE_CODE (t) == REAL_CST && !flag_signed_zeros)
zerop = REAL_VALUES_IDENTICAL (TREE_REAL_CST (t), dconst0);
else if (TREE_CODE (t) == FIXED_CST)
zerop = fixed_zerop (t);