diff --git a/gcc/expr.cc b/gcc/expr.cc index c37a9990536..78c839ab425 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 00000000000..ce5f6b2741c --- /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 00000000000..ac33340099b --- /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" } } */