summaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2004-12-20 23:04:37 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2004-12-20 23:04:37 +0000
commitccd5a3effe88410cb99f135bda8e20a95b8f1ea7 (patch)
tree2e5a8433ef74f4121b60230ab0144e0d67dd6523 /gcc/expr.c
parentc5703f4d3e833a4b750a4c542cc1d390732df8b1 (diff)
downloadgcc-ccd5a3effe88410cb99f135bda8e20a95b8f1ea7.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@92440 138bc75d-0d04-0410-961f-82ee72b054a4
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 de11afffe3f..bfc6b68af4d 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,