> --- 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