This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/43108 (performance regression on mixed complex/real arithmetic)


I don't claim to understand the underlying issues here, but the comments in the PR pointed out that Joseph had fixed the same issue in the C front end, so I just adapted his code to the equivalent function in the C++ front end, and moved his tests into c-c++-common. And then fixed another bug that was preventing them from compiling.

The attached patch includes the changes I made to the tests so that they will compile as C++ as well. I verified that this patch fixes the testcase in the PR, but did not add it to the testsuite, since we now run the tests from Joseph.

Tested x86_64-pc-linux-gnu, applied to trunk.
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.

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/c-c++-common/complex-alias-1.c b/gcc/testsuite/c-c++-common/complex-alias-1.c
index 6ab4ca0..cdf832d 100644
--- a/gcc/testsuite/c-c++-common/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/c-c++-common/complex-sign-add.c b/gcc/testsuite/c-c++-common/complex-sign-add.c
index db92140..e812232 100644
--- a/gcc/testsuite/c-c++-common/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/c-c++-common/complex-sign-mixed-add.c b/gcc/testsuite/c-c++-common/complex-sign-mixed-add.c
index 5548fe4..d1e2091 100644
--- a/gcc/testsuite/c-c++-common/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/c-c++-common/complex-sign-mixed-div.c b/gcc/testsuite/c-c++-common/complex-sign-mixed-div.c
index 4a315dc..f7ee483 100644
--- a/gcc/testsuite/c-c++-common/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/c-c++-common/complex-sign-mixed-mul.c b/gcc/testsuite/c-c++-common/complex-sign-mixed-mul.c
index f5b1fc4..02f936b 100644
--- a/gcc/testsuite/c-c++-common/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/c-c++-common/complex-sign-mixed-sub.c b/gcc/testsuite/c-c++-common/complex-sign-mixed-sub.c
index adc3845..739500d 100644
--- a/gcc/testsuite/c-c++-common/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/c-c++-common/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/c-c++-common/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/c-c++-common/complex-sign-mul-one.c b/gcc/testsuite/c-c++-common/complex-sign-mul-one.c
index 9d1d6c7..014d813 100644
--- a/gcc/testsuite/c-c++-common/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/c-c++-common/complex-sign-mul.c b/gcc/testsuite/c-c++-common/complex-sign-mul.c
index d9a06a5..08d247a 100644
--- a/gcc/testsuite/c-c++-common/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/c-c++-common/complex-sign-sub.c b/gcc/testsuite/c-c++-common/complex-sign-sub.c
index 94ab17d..d4da14d 100644
--- a/gcc/testsuite/c-c++-common/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/c-c++-common/complex-sign.h b/gcc/testsuite/c-c++-common/complex-sign.h
index f12e25d..9626110 100644
--- a/gcc/testsuite/c-c++-common/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 {								\

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]