aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-02-18 14:58:41 -0500
committerJason Merrill <jason@gcc.gnu.org>2010-02-18 14:58:41 -0500
commit1ff6b2c8c471291a07ba054ddbd18acb9dd69d7a (patch)
tree651108caa02b6a01d8cc48219d48abf71d7fb4e4
parent86866b288ea526e0f6721cebb78d0dc5c2126254 (diff)
downloadgcc-1ff6b2c8c471291a07ba054ddbd18acb9dd69d7a.zip
gcc-1ff6b2c8c471291a07ba054ddbd18acb9dd69d7a.tar.gz
gcc-1ff6b2c8c471291a07ba054ddbd18acb9dd69d7a.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/cvt.c6
-rw-r--r--gcc/cp/typeck.c80
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/c-c++-common/complex-alias-1.c (renamed from gcc/testsuite/gcc.dg/torture/complex-alias-1.c)8
-rw-r--r--gcc/testsuite/c-c++-common/complex-sign-add.c (renamed from gcc/testsuite/gcc.dg/torture/complex-sign-add.c)2
-rw-r--r--gcc/testsuite/c-c++-common/complex-sign-mixed-add.c (renamed from gcc/testsuite/gcc.dg/torture/complex-sign-mixed-add.c)2
-rw-r--r--gcc/testsuite/c-c++-common/complex-sign-mixed-div.c (renamed from gcc/testsuite/gcc.dg/torture/complex-sign-mixed-div.c)2
-rw-r--r--gcc/testsuite/c-c++-common/complex-sign-mixed-mul.c (renamed from gcc/testsuite/gcc.dg/torture/complex-sign-mixed-mul.c)2
-rw-r--r--gcc/testsuite/c-c++-common/complex-sign-mixed-sub.c (renamed from gcc/testsuite/gcc.dg/torture/complex-sign-mixed-sub.c)2
-rw-r--r--gcc/testsuite/c-c++-common/complex-sign-mul-minus-one.c (renamed from gcc/testsuite/gcc.dg/torture/complex-sign-mul-minus-one.c)2
-rw-r--r--gcc/testsuite/c-c++-common/complex-sign-mul-one.c (renamed from gcc/testsuite/gcc.dg/torture/complex-sign-mul-one.c)2
-rw-r--r--gcc/testsuite/c-c++-common/complex-sign-mul.c (renamed from gcc/testsuite/gcc.dg/torture/complex-sign-mul.c)2
-rw-r--r--gcc/testsuite/c-c++-common/complex-sign-sub.c (renamed from gcc/testsuite/gcc.dg/torture/complex-sign-sub.c)2
-rw-r--r--gcc/testsuite/c-c++-common/complex-sign.h (renamed from gcc/testsuite/gcc.dg/torture/complex-sign.h)6
16 files changed, 123 insertions, 16 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a54d30a..3140ecf 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8b5bb56..aff3f91 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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. */
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 9dd0c59..344816c 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -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)))
{
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 18d56f4..01384de 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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)))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f3957e1..db7fa41 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,16 @@
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.
diff --git a/gcc/testsuite/gcc.dg/torture/complex-alias-1.c b/gcc/testsuite/c-c++-common/complex-alias-1.c
index 6ab4ca0..cdf832d 100644
--- a/gcc/testsuite/gcc.dg/torture/complex-alias-1.c
+++ b/gcc/testsuite/c-c++-common/complex-alias-1.c
@@ -1,9 +1,15 @@
/* 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;
}
diff --git a/gcc/testsuite/gcc.dg/torture/complex-sign-add.c b/gcc/testsuite/c-c++-common/complex-sign-add.c
index db92140..e812232 100644
--- a/gcc/testsuite/gcc.dg/torture/complex-sign-add.c
+++ b/gcc/testsuite/c-c++-common/complex-sign-add.c
@@ -1,7 +1,7 @@
/* 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"
diff --git a/gcc/testsuite/gcc.dg/torture/complex-sign-mixed-add.c b/gcc/testsuite/c-c++-common/complex-sign-mixed-add.c
index 5548fe4..d1e2091 100644
--- a/gcc/testsuite/gcc.dg/torture/complex-sign-mixed-add.c
+++ b/gcc/testsuite/c-c++-common/complex-sign-mixed-add.c
@@ -1,7 +1,7 @@
/* 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"
diff --git a/gcc/testsuite/gcc.dg/torture/complex-sign-mixed-div.c b/gcc/testsuite/c-c++-common/complex-sign-mixed-div.c
index 4a315dc..f7ee483 100644
--- a/gcc/testsuite/gcc.dg/torture/complex-sign-mixed-div.c
+++ b/gcc/testsuite/c-c++-common/complex-sign-mixed-div.c
@@ -1,7 +1,7 @@
/* 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"
diff --git a/gcc/testsuite/gcc.dg/torture/complex-sign-mixed-mul.c b/gcc/testsuite/c-c++-common/complex-sign-mixed-mul.c
index f5b1fc4..02f936b 100644
--- a/gcc/testsuite/gcc.dg/torture/complex-sign-mixed-mul.c
+++ b/gcc/testsuite/c-c++-common/complex-sign-mixed-mul.c
@@ -1,7 +1,7 @@
/* 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"
diff --git a/gcc/testsuite/gcc.dg/torture/complex-sign-mixed-sub.c b/gcc/testsuite/c-c++-common/complex-sign-mixed-sub.c
index adc3845..739500d 100644
--- a/gcc/testsuite/gcc.dg/torture/complex-sign-mixed-sub.c
+++ b/gcc/testsuite/c-c++-common/complex-sign-mixed-sub.c
@@ -1,7 +1,7 @@
/* 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"
diff --git a/gcc/testsuite/gcc.dg/torture/complex-sign-mul-minus-one.c b/gcc/testsuite/c-c++-common/complex-sign-mul-minus-one.c
index 6b9a905..05cc4fa 100644
--- a/gcc/testsuite/gcc.dg/torture/complex-sign-mul-minus-one.c
+++ b/gcc/testsuite/c-c++-common/complex-sign-mul-minus-one.c
@@ -1,7 +1,7 @@
/* 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"
diff --git a/gcc/testsuite/gcc.dg/torture/complex-sign-mul-one.c b/gcc/testsuite/c-c++-common/complex-sign-mul-one.c
index 9d1d6c7..014d813 100644
--- a/gcc/testsuite/gcc.dg/torture/complex-sign-mul-one.c
+++ b/gcc/testsuite/c-c++-common/complex-sign-mul-one.c
@@ -1,7 +1,7 @@
/* 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"
diff --git a/gcc/testsuite/gcc.dg/torture/complex-sign-mul.c b/gcc/testsuite/c-c++-common/complex-sign-mul.c
index d9a06a5..08d247a 100644
--- a/gcc/testsuite/gcc.dg/torture/complex-sign-mul.c
+++ b/gcc/testsuite/c-c++-common/complex-sign-mul.c
@@ -1,7 +1,7 @@
/* 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"
diff --git a/gcc/testsuite/gcc.dg/torture/complex-sign-sub.c b/gcc/testsuite/c-c++-common/complex-sign-sub.c
index 94ab17d..d4da14d 100644
--- a/gcc/testsuite/gcc.dg/torture/complex-sign-sub.c
+++ b/gcc/testsuite/c-c++-common/complex-sign-sub.c
@@ -1,7 +1,7 @@
/* 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"
diff --git a/gcc/testsuite/gcc.dg/torture/complex-sign.h b/gcc/testsuite/c-c++-common/complex-sign.h
index f12e25d..9626110 100644
--- a/gcc/testsuite/gcc.dg/torture/complex-sign.h
+++ b/gcc/testsuite/c-c++-common/complex-sign.h
@@ -1,7 +1,13 @@
/* 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 { \