On Mar 30, 2011, at 9:05 AM, Jakub Jelinek <ja...@redhat.com> wrote:
> +       else if (bitpos >= mode_bitsize / 2)
> +         result = store_field (XEXP (to_rtx, 1), bitsize,
> +                               bitpos - mode_bitsize / 2, mode1, from,
> +                               TREE_TYPE (tem), get_alias_set (to),
> +                               nontemporal);

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

I think this is bad.  I think this patch fixes it.  The problem is that we 
can't write outside the bounds of the object.  So, instead we punt out of the 
register case, and instead spill it to memory that _is_ big enough, and then 
spill it back to registers.  Of course, I'd rather emit a diagnostic when extra 
is non-zero…  but not sure people yet buy into that around here.

Thoughts?

diff --git a/gcc/expr.c b/gcc/expr.c
index 923f59b..f5744b0 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4815,7 +4815,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
                                  bitregion_start, bitregion_end,
                                  mode1, from,
                                  get_alias_set (to), nontemporal);
-         else if (bitpos >= mode_bitsize / 2)
+         else if (bitpos >= mode_bitsize / 2
+                  && bitpos+bitsize <= mode_bitsize)
            result = store_field (XEXP (to_rtx, 1), bitsize,
                                  bitpos - mode_bitsize / 2,
                                  bitregion_start, bitregion_end,
@@ -4834,8 +4835,12 @@ expand_assignment (tree to, tree from, bool nontemporal)
            }
          else
            {
+             HOST_WIDE_INT extra = 0;
+             if (bitpos+bitsize > mode_bitsize)
+               extra = bitpos+bitsize - mode_bitsize;
              rtx temp = assign_stack_temp (GET_MODE (to_rtx),
-                                           GET_MODE_SIZE (GET_MODE (to_rtx)));
+                                           GET_MODE_SIZE (GET_MODE (to_rtx))
+                                           + extra);
              write_complex_part (temp, XEXP (to_rtx, 0), false);
              write_complex_part (temp, XEXP (to_rtx, 1), true);
              result = store_field (temp, bitsize, bitpos,

Reply via email to