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]

[PATCH] Fix expansion of VCE from complex mode (PR middle-end/40446)


Hi!

gen_lowpart with COMPLEX_MODE_P (GET_MODE (op0)) will usually crash if op0
isn't a MEM (but if it is a MEM, the later code in expand_expr_real_1 will
handle it just fine), because for complex modes CONCAT is created instead of
REG by force_operand/force_reg/... and gen_lowpart can only handle CONCAT if
the target mode doesn't cover both registers in the CONCAT, but just one,
and VCE needs the same size mode as the whole CONCAT.

gen_lowpart_general perhaps could temporarily set generating_concat_p = 0,
but we risk it increases register pressure too much, so this patch just
let's it go through MEM.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.4?

2009-06-16  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/40446
	* expr.c (expand_expr_real_1) <case VIEW_CONVERT_EXPR>: Don't
	use gen_lowpart if op0 has complex mode.

	* g++.dg/other/pr40446.C: New test.

--- gcc/expr.c.jj	2009-06-08 11:53:58.000000000 +0200
+++ gcc/expr.c	2009-06-16 10:28:19.000000000 +0200
@@ -8319,7 +8319,8 @@ expand_expr_real_1 (tree exp, rtx target
       /* If neither mode is BLKmode, and both modes are the same size
 	 then we can use gen_lowpart.  */
       else if (mode != BLKmode && GET_MODE (op0) != BLKmode
-	       && GET_MODE_SIZE (mode) == GET_MODE_SIZE (GET_MODE (op0)))
+	       && GET_MODE_SIZE (mode) == GET_MODE_SIZE (GET_MODE (op0))
+	       && !COMPLEX_MODE_P (GET_MODE (op0)))
 	{
 	  if (GET_CODE (op0) == SUBREG)
 	    op0 = force_reg (GET_MODE (op0), op0);
--- gcc/testsuite/g++.dg/other/pr40446.C.jj	2009-06-16 10:40:23.000000000 +0200
+++ gcc/testsuite/g++.dg/other/pr40446.C	2009-06-16 10:53:45.000000000 +0200
@@ -0,0 +1,46 @@
+// PR middle-end/40446
+// { dg-do run { target i?86-*-* x86_64-*-* } }
+// { dg-options "-O1 -msse2" }
+
+#include <emmintrin.h>
+#include "cpuid.h"
+
+extern "C" void abort ();
+
+struct S
+{
+  S (double r, double i) { __real__ s = r; __imag__ s = i; }
+  __complex__ double s;
+};
+
+__m128d
+foo ()
+{
+  S c (0, 1);
+  return _mm_load_pd ((double *) &c);
+}
+
+static void
+__attribute__((noinline))
+sse2_test ()
+{
+  union { __m128d vec; double val[2]; } u;
+  u.vec = foo ();
+  if (u.val[0] != 0 || u.val[1] != 1)
+    abort ();
+}
+
+int
+main ()
+{
+  unsigned int eax, ebx, ecx, edx;
+
+  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+    return 0;
+
+  /* Run SSE2 test only if host has SSE2 support.  */
+  if (edx & bit_SSE2)
+    sse2_test ();
+
+  return 0;
+}

	Jakub


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