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

Reply via email to