aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/expr.cc18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr7061-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr7061-2.c5
3 files changed, 26 insertions, 1 deletions
diff --git a/gcc/expr.cc b/gcc/expr.cc
index c37a999..78c839a 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -2801,10 +2801,26 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED,
{
machine_mode dest_mode = GET_MODE (dest);
machine_mode tmp_mode = GET_MODE (tmps[i]);
+ scalar_int_mode imode;
gcc_assert (known_eq (bytepos, 0) && XVECLEN (src, 0));
- if (GET_MODE_ALIGNMENT (dest_mode)
+ if (finish == 1
+ && REG_P (tmps[i])
+ && COMPLEX_MODE_P (dest_mode)
+ && SCALAR_INT_MODE_P (tmp_mode)
+ && int_mode_for_mode (dest_mode).exists (&imode))
+ {
+ if (tmp_mode != imode)
+ {
+ rtx tmp = gen_reg_rtx (imode);
+ emit_move_insn (tmp, gen_lowpart (imode, tmps[i]));
+ dst = gen_lowpart (dest_mode, tmp);
+ }
+ else
+ dst = gen_lowpart (dest_mode, tmps[i]);
+ }
+ else if (GET_MODE_ALIGNMENT (dest_mode)
>= GET_MODE_ALIGNMENT (tmp_mode))
{
dest = assign_stack_temp (dest_mode,
diff --git a/gcc/testsuite/gcc.target/i386/pr7061-1.c b/gcc/testsuite/gcc.target/i386/pr7061-1.c
new file mode 100644
index 0000000..ce5f6b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr7061-1.c
@@ -0,0 +1,4 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+float re(float _Complex a) { return __real__ a; }
+/* { dg-final { scan-assembler-not "mov" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr7061-2.c b/gcc/testsuite/gcc.target/i386/pr7061-2.c
new file mode 100644
index 0000000..ac33340
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr7061-2.c
@@ -0,0 +1,5 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+float im(float _Complex a) { return __imag__ a; }
+/* { dg-final { scan-assembler-not "movss" } } */
+/* { dg-final { scan-assembler-not "rsp" } } */