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

login
register
mail settings
Submitter Mike Stump
Date Aug. 9, 2013, 12:15 a.m.
Message ID <31B3A889-7A2A-49B0-B0D9-45624C4212DC@comcast.net>
Download mbox | patch
Permalink /patch/265866/
State New
Headers show

Comments

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

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,