Commit 1ff6b2c8 by Jason Merrill Committed by Jason Merrill

re PR c++/43108 (mixed complex<T> multiplication horribly inefficient)

	PR c++/43108
	* typeck.c (cp_build_binary_op): Adapt mixed complex/non handling from
	C build_binary_op.
	* cp-tree.h (WANT_VECTOR_OR_COMPLEX): Rename from WANT_VECTOR.
	* cvt.c (build_expr_type_conversion): Allow COMPLEX_TYPE.

From-SVN: r156874
parent 86866b28
2010-02-18 Jason Merrill <jason@redhat.com>
PR c++/43108
* typeck.c (cp_build_binary_op): Adapt mixed complex/non handling from
C build_binary_op.
* cp-tree.h (WANT_VECTOR_OR_COMPLEX): Rename from WANT_VECTOR.
* cvt.c (build_expr_type_conversion): Allow COMPLEX_TYPE.
PR c++/43070
* semantics.c (finish_goto_stmt): Don't call decay_conversion.
......
......@@ -4167,8 +4167,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
#define WANT_ENUM 4 /* enumerated types */
#define WANT_POINTER 8 /* pointer types */
#define WANT_NULL 16 /* null pointer constant */
#define WANT_VECTOR 32 /* vector types */
#define WANT_ARITH (WANT_INT | WANT_FLOAT | WANT_VECTOR)
#define WANT_VECTOR_OR_COMPLEX 32 /* vector or complex types */
#define WANT_ARITH (WANT_INT | WANT_FLOAT | WANT_VECTOR_OR_COMPLEX)
/* Used with comptypes, and related functions, to guide type
comparison. */
......
......@@ -1170,8 +1170,9 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
return (desires & WANT_POINTER) ? decay_conversion (expr)
: NULL_TREE;
case COMPLEX_TYPE:
case VECTOR_TYPE:
if ((desires & WANT_VECTOR) == 0)
if ((desires & WANT_VECTOR_OR_COMPLEX) == 0)
return NULL_TREE;
switch (TREE_CODE (TREE_TYPE (basetype)))
{
......@@ -1226,8 +1227,9 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
case POINTER_TYPE:
win = (desires & WANT_POINTER); break;
case COMPLEX_TYPE:
case VECTOR_TYPE:
if ((desires & WANT_VECTOR) == 0)
if ((desires & WANT_VECTOR_OR_COMPLEX) == 0)
break;
switch (TREE_CODE (TREE_TYPE (candidate)))
{
......
......@@ -4230,7 +4230,83 @@ cp_build_binary_op (location_t location,
if (arithmetic_types_p)
{
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);
/* Adapted from patch for c/24581. */
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 (first_complex)
{
if (TREE_TYPE (op0) != result_type)
op0 = cp_convert_and_check (result_type, op0);
if (TREE_TYPE (op1) != real_type)
op1 = cp_convert_and_check (real_type, op1);
}
else
{
if (TREE_TYPE (op0) != real_type)
op0 = cp_convert_and_check (real_type, op0);
if (TREE_TYPE (op1) != result_type)
op1 = cp_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 = save_expr (op0);
real = cp_build_unary_op (REALPART_EXPR, op0, 1, complain);
imag = cp_build_unary_op (IMAGPART_EXPR, op0, 1, complain);
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 = save_expr (op1);
real = cp_build_unary_op (REALPART_EXPR, op1, 1, complain);
imag = cp_build_unary_op (IMAGPART_EXPR, op1, 1, complain);
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();
}
}
return build2 (COMPLEX_EXPR, result_type, real, imag);
}
/* For certain operations (which identify themselves by shorten != 0)
if both args were extended from the same smaller type,
......@@ -4615,7 +4691,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
arg = default_conversion (arg);
}
else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM
| WANT_VECTOR,
| WANT_VECTOR_OR_COMPLEX,
arg, true)))
errstring = _("wrong type argument to bit-complement");
else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg)))
......
2010-02-18 Jason Merrill <jason@redhat.com>
PR c++/43108
* c-c++-common/complex-sign.h,
c-c++-common/complex-sign-add.c,
c-c++-common/complex-sign-mixed-add.c,
c-c++-common/complex-sign-mixed-div.c,
c-c++-common/complex-sign-mixed-mul.c,
c-c++-common/complex-sign-mixed-sub.c,
c-c++-common/complex-sign-mul.c,
c-c++-common/complex-sign-sub.c: Move from gcc.dg/torture.
Adapt for C++ compilation as well.
PR c++/43070
* g++.dg/ext/label1.C: Update.
* g++.dg/ext/label2.C: Update.
......
/* Accesses to complex numbers were sometimes marked as scalar and
sometimes as struct accesses. */
/* { dg-do run } */
/* { dg-options "-std=c99" } */
/* { dg-options "-std=c99" { target c } } */
#ifdef __cplusplus
extern "C" {
#endif
extern void abort (void);
#ifdef __cplusplus
}
#endif
static double _Complex *fp_cxd(double _Complex *cx) {
return cx;
}
......
/* Test complex arithmetic with signed zeros. Pure complex
addition. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
......
/* Test complex arithmetic with signed zeros. Mixed real/complex
addition. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
......
/* Test complex arithmetic with signed zeros. Mixed real/complex
division. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
......
/* Test complex arithmetic with signed zeros. Mixed real/complex
multiplication. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
......
/* Test complex arithmetic with signed zeros. Mixed real/complex
subtraction. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
......
/* Test complex arithmetic with signed zeros. Pure complex
multiplication with -1.0 + 0.0i. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
......
/* Test complex arithmetic with signed zeros. Pure complex
multiplication with 1.0 + 0.0i. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
......
/* Test complex arithmetic with signed zeros. Pure complex
multiplication. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
......
/* Test complex arithmetic with signed zeros. Pure complex
subtraction. */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
......
/* Common header for complex arithmetic sign tests. */
#ifdef __cplusplus
extern "C" {
#endif
extern void abort (void);
extern void exit (int);
#ifdef __cplusplus
}
#endif
#define CHECK_RES(VALUE, COPY, SIGN_REAL, SIGN_IMAG) \
do { \
......
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