summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/expr.c3
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/other/pr40446.C46
4 files changed, 59 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 524f71e8fca..bbf4e60feb8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+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.
+
2009-06-16 Richard Guenther <rguenther@suse.de>
* tree-ssa-structalias.c (do_ds_constraint): Stores in global
diff --git a/gcc/expr.c b/gcc/expr.c
index ec1800e63a2..34137c0cd07 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8321,7 +8321,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
/* 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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fd2ca7357dc..689597830a7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-06-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40446
+ * g++.dg/other/pr40446.C: New test.
+
2009-06-16 Richard Guenther <rguenther@suse.de>
* gcc.dg/tree-ssa/pta-escape-1.c: New testcase.
diff --git a/gcc/testsuite/g++.dg/other/pr40446.C b/gcc/testsuite/g++.dg/other/pr40446.C
new file mode 100644
index 00000000000..33dbcec7159
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/pr40446.C
@@ -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;
+}