diff options
author | Jason Merrill <jason@redhat.com> | 2010-02-18 14:58:41 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2010-02-18 14:58:41 -0500 |
commit | 1ff6b2c8c471291a07ba054ddbd18acb9dd69d7a (patch) | |
tree | 651108caa02b6a01d8cc48219d48abf71d7fb4e4 | |
parent | 86866b288ea526e0f6721cebb78d0dc5c2126254 (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 6 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 80 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 11 | ||||
-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 { \ |