aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@libertysurf.fr>2004-12-21 00:04:37 +0100
committerEric Botcazou <ebotcazou@gcc.gnu.org>2004-12-20 23:04:37 +0000
commit36d7571c0d377bd9a4e40d55ad803e6bf7b55cd9 (patch)
tree2e5a8433ef74f4121b60230ab0144e0d67dd6523 /gcc/expr.c
parentdef9360c67e43763c98a0579164ce400fc9f411c (diff)
downloadgcc-36d7571c0d377bd9a4e40d55ad803e6bf7b55cd9.zip
gcc-36d7571c0d377bd9a4e40d55ad803e6bf7b55cd9.tar.gz
gcc-36d7571c0d377bd9a4e40d55ad803e6bf7b55cd9.tar.bz2
re PR middle-end/18776 (Libgfortran doesn't build again)
PR middle-end/18776 * expr.c (write_complex_part): Use a subreg if the original object is a hard reg that spans an even number of regs or a MEM. (read_complex_part): Likewise. From-SVN: r92440
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c46
1 files changed, 39 insertions, 7 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index de11afff..bfc6b68 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2598,14 +2598,32 @@ write_complex_part (rtx cplx, rtx val, bool imag_p)
will work. This special case is important, since store_bit_field
wants to operate on integer modes, and there's rarely an OImode to
correspond to TCmode. */
- if (ibitsize >= BITS_PER_WORD)
+ if (ibitsize >= BITS_PER_WORD
+ /* For hard regs we have exact predicates. Assume we can split
+ the original object if it spans an even number of hard regs.
+ This special case is important for SCmode on 64-bit platforms
+ where the natural size of floating-point regs is 32-bit. */
+ || (GET_CODE (cplx) == REG
+ && REGNO (cplx) < FIRST_PSEUDO_REGISTER
+ && hard_regno_nregs[REGNO (cplx)][cmode] % 2 == 0)
+ /* For MEMs we always try to make a "subreg", that is to adjust
+ the MEM, because store_bit_field may generate overly
+ convoluted RTL for sub-word fields. */
+ || MEM_P (cplx))
{
rtx part = simplify_gen_subreg (imode, cplx, cmode,
imag_p ? GET_MODE_SIZE (imode) : 0);
- emit_move_insn (part, val);
+ if (part)
+ {
+ emit_move_insn (part, val);
+ return;
+ }
+ else
+ /* simplify_gen_subreg may fail for sub-word MEMs. */
+ gcc_assert (MEM_P (cplx) && ibitsize < BITS_PER_WORD);
}
- else
- store_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0, imode, val);
+
+ store_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0, imode, val);
}
/* Extract one of the components of the complex value CPLX. Extract the
@@ -2640,12 +2658,26 @@ read_complex_part (rtx cplx, bool imag_p)
will work. This special case is important, since extract_bit_field
wants to operate on integer modes, and there's rarely an OImode to
correspond to TCmode. */
- if (ibitsize >= BITS_PER_WORD)
+ if (ibitsize >= BITS_PER_WORD
+ /* For hard regs we have exact predicates. Assume we can split
+ the original object if it spans an even number of hard regs.
+ This special case is important for SCmode on 64-bit platforms
+ where the natural size of floating-point regs is 32-bit. */
+ || (GET_CODE (cplx) == REG
+ && REGNO (cplx) < FIRST_PSEUDO_REGISTER
+ && hard_regno_nregs[REGNO (cplx)][cmode] % 2 == 0)
+ /* For MEMs we always try to make a "subreg", that is to adjust
+ the MEM, because extract_bit_field may generate overly
+ convoluted RTL for sub-word fields. */
+ || MEM_P (cplx))
{
rtx ret = simplify_gen_subreg (imode, cplx, cmode,
imag_p ? GET_MODE_SIZE (imode) : 0);
- gcc_assert (ret != NULL);
- return ret;
+ if (ret)
+ return ret;
+ else
+ /* simplify_gen_subreg may fail for sub-word MEMs. */
+ gcc_assert (MEM_P (cplx) && ibitsize < BITS_PER_WORD);
}
return extract_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0,