Fix expansion issues on type changing MEM_REFs on LHS (PR middle-end/48335)

Submitted by Mike Stump on Aug. 9, 2013, 12:15 a.m.

Details

Message ID 31B3A889-7A2A-49B0-B0D9-45624C4212DC@comcast.net
State New
Headers show

Commit Message

Mike Stump Aug. 9, 2013, 12:15 a.m.
On Mar 30, 2011, at 9:05 AM, Jakub Jelinek <jakub@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?

Patch hide | download patch | download mbox

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,