> --- gcc/expr.c.jj 2011-03-23 17:15:55.000000000 +0100
> +++ gcc/expr.c 2011-03-30 11:38:15.000000000 +0200
> @@ -4278,16 +4278,47 @@ expand_assignment (tree to, tree from, b
> /* Handle expand_expr of a complex value returning a CONCAT. */
> else if (GET_CODE (to_rtx) == CONCAT)
> {
> - if (COMPLEX_MODE_P (TYPE_MODE (TREE_TYPE (from))))
> + unsigned short mode_bitsize = GET_MODE_BITSIZE (GET_MODE (to_rtx));
> + if (COMPLEX_MODE_P (TYPE_MODE (TREE_TYPE (from)))
> + && bitpos == 0
> + && bitsize == mode_bitsize)
> + result = store_expr (from, to_rtx, false, nontemporal);
> + else if (bitsize == mode_bitsize / 2
> + && (bitpos == 0 || bitpos == GET_MODE_BITSIZE (mode1)))
> + result = store_expr (from, XEXP (to_rtx, bitpos != 0), false,
> + nontemporal);
Why GET_MODE_BITSIZE (mode1) and not mode_bitsize / 2 here?
> {
> - gcc_assert (bitpos == 0 || bitpos == GET_MODE_BITSIZE (mode1));
> - result = store_expr (from, XEXP (to_rtx, bitpos != 0), false,
> - nontemporal);
> + rtx temp = assign_stack_temp (GET_MODE (to_rtx),
> + GET_MODE_SIZE (GET_MODE (to_rtx)),
> + 0);
> + write_complex_part (temp, XEXP (to_rtx, 0), false);
> + write_complex_part (temp, XEXP (to_rtx, 1), true);
> + result = store_field (temp, bitsize, bitpos, mode1, from,
> + TREE_TYPE (tem), get_alias_set (to),
> + nontemporal);
> + emit_move_insn (XEXP (to_rtx, 0), read_complex_part (temp,
> false));
> + emit_move_insn (XEXP (to_rtx, 1), read_complex_part (temp, true));
> }
Can't you add result = NULL at the end of the block?
> : (! SLOW_UNALIGNED_ACCESS (fieldmode, MEM_ALIGN (op0))
> :
> || (offset * BITS_PER_UNIT % bitsize == 0
>
> - && MEM_ALIGN (op0) % GET_MODE_BITSIZE (fieldmode) == 0))))
> + && MEM_ALIGN (op0) % GET_MODE_BITSIZE (fieldmode) == 0)))
> + && (MEM_P (op0)
> + || GET_MODE (op0) == fieldmode
> + || validate_subreg (fieldmode, GET_MODE (op0), op0, byte_offset)))
This partially duplicates the existing test. Can't the new code be retrofitted
into the existing test?
> @@ -1045,22 +1052,32 @@ store_split_bit_field (rtx op0, unsigned
> if (GET_CODE (op0) == SUBREG)
> {
> int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
> - word = operand_subword_force (SUBREG_REG (op0), word_offset,
> - GET_MODE (SUBREG_REG (op0)));
> + enum machine_mode sub_mode = GET_MODE (SUBREG_REG (op0));
> + if (sub_mode != BLKmode && GET_MODE_SIZE (sub_mode) < UNITS_PER_WORD)
> + word = word_offset ? const0_rtx : op0;
> + else
> + word = operand_subword_force (SUBREG_REG (op0), word_offset,
> + GET_MODE (SUBREG_REG (op0)));
> offset = 0;
> }
> else if (REG_P (op0))
> {
> - word = operand_subword_force (op0, offset, GET_MODE (op0));
> + enum machine_mode op0_mode = GET_MODE (op0);
> + if (op0_mode != BLKmode && GET_MODE_SIZE (op0_mode) < UNITS_PER_WORD)
> + word = offset ? const0_rtx : op0;
> + else
> + word = operand_subword_force (op0, offset, GET_MODE (op0));
> offset = 0;
> }
> else
> word = op0;
>
> /* OFFSET is in UNITs, and UNIT is in bits.
> - store_fixed_bit_field wants offset in bytes. */
> - store_fixed_bit_field (word, offset * unit / BITS_PER_UNIT,
> thissize, - thispos, part);
> + store_fixed_bit_field wants offset in bytes. If WORD is const0_rtx,
> + it is jut an out of bounds access. Ignore it. */
> + if (word != const0_rtx)
> + store_fixed_bit_field (word, offset * unit / BITS_PER_UNIT, thissize,
> + thispos, part);
> bitsdone += thissize;
"it is just an out-of-bounds access."
--
Eric Botcazou