Commit 2ca862e9 by Joseph Myers Committed by Joseph Myers

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
parent cb8e4445
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> 2009-05-08 Paolo Bonzini <bonzini@gnu.org>
PR rtl-optimization/33928 PR rtl-optimization/33928
......
...@@ -9246,7 +9246,9 @@ build_binary_op (location_t location, enum tree_code code, ...@@ -9246,7 +9246,9 @@ build_binary_op (location_t location, enum tree_code code,
(code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
|| code1 == FIXED_POINT_TYPE || code1 == VECTOR_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) if (shorten || common || short_compare)
{ {
...@@ -9255,6 +9257,89 @@ build_binary_op (location_t location, enum tree_code code, ...@@ -9255,6 +9257,89 @@ build_binary_op (location_t location, enum tree_code code,
return error_mark_node; 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) /* For certain operations (which identify themselves by shorten != 0)
if both args were extended from the same smaller type, if both args were extended from the same smaller type,
do the arithmetic in that type and then extend. do the arithmetic in that type and then extend.
......
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> 2009-05-08 Janus Weil <janus@gcc.gnu.org>
PR fortran/39876 PR fortran/39876
......
/* 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);
}
/* 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);
}
/* 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);
}
/* 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);
}
/* 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);
}
/* 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);
}
/* 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);
}
/* 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)
...@@ -99,7 +99,10 @@ some_nonzerop (tree t) ...@@ -99,7 +99,10 @@ some_nonzerop (tree t)
{ {
int zerop = false; 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); zerop = REAL_VALUES_IDENTICAL (TREE_REAL_CST (t), dconst0);
else if (TREE_CODE (t) == FIXED_CST) else if (TREE_CODE (t) == FIXED_CST)
zerop = fixed_zerop (t); zerop = fixed_zerop (t);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment