diff mbox series

Fix expand_assignment stores to CONCAT (PR middle-end/83609)

Message ID 20171230193159.GN1833@tucnak
State New
Headers show
Series Fix expand_assignment stores to CONCAT (PR middle-end/83609) | expand

Commit Message

Jakub Jelinek Dec. 30, 2017, 7:31 p.m. UTC
Hi!

The first hunk before the if (!from...) part shows a typo I've made in a
recent change, the last argument of simplify_gen_subreg is byte offset, and
the subreg has same bitsize outer and inner modes, so using byte offset 1
makes no sense at all.
Another issue that the testcase suffers from is that the simplify_gen_rtx
(preexisting issue) can fail, and in that case trying to read_complex_part
from that NULL will ICE.  The patch tries harder by trying to simplify the
2 halves separately, and for all cases when simplify_gen_subreg fails which
can happen because of various reasons, there is the fallback to go through
memory.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/7.3?

2017-12-30  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/83609
	* expr.c (expand_assignment): Fix up a typo in simplify_gen_subreg
	last argument when extracting from CONCAT.  If either from_real or
	from_imag is NULL, use expansion through memory.  If result is not
	a CONCAT and simplify_gen_subreg fails, try to simplify_gen_subreg
	the parts directly to inner mode, if even that fails, use expansion
	through memory.

	* gcc.dg/pr83609.c: New test.
	* g++.dg/opt/pr83609.C: New test.


	Jakub

Comments

Richard Biener Dec. 31, 2017, 7:45 a.m. UTC | #1
On December 30, 2017 8:31:59 PM GMT+01:00, Jakub Jelinek <jakub@redhat.com> wrote:
>Hi!
>
>The first hunk before the if (!from...) part shows a typo I've made in
>a
>recent change, the last argument of simplify_gen_subreg is byte offset,
>and
>the subreg has same bitsize outer and inner modes, so using byte offset
>1
>makes no sense at all.
>Another issue that the testcase suffers from is that the
>simplify_gen_rtx
>(preexisting issue) can fail, and in that case trying to
>read_complex_part
>from that NULL will ICE.  The patch tries harder by trying to simplify
>the
>2 halves separately, and for all cases when simplify_gen_subreg fails
>which
>can happen because of various reasons, there is the fallback to go
>through
>memory.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for
>trunk/7.3?

OK. 

Richard. 

>2017-12-30  Jakub Jelinek  <jakub@redhat.com>
>
>	PR middle-end/83609
>	* expr.c (expand_assignment): Fix up a typo in simplify_gen_subreg
>	last argument when extracting from CONCAT.  If either from_real or
>	from_imag is NULL, use expansion through memory.  If result is not
>	a CONCAT and simplify_gen_subreg fails, try to simplify_gen_subreg
>	the parts directly to inner mode, if even that fails, use expansion
>	through memory.
>
>	* gcc.dg/pr83609.c: New test.
>	* g++.dg/opt/pr83609.C: New test.
>
>--- gcc/expr.c.jj	2017-12-21 09:43:19.797042465 +0100
>+++ gcc/expr.c	2017-12-30 13:49:19.634057445 +0100
>@@ -5158,7 +5158,9 @@ expand_assignment (tree to, tree from, b
> 					   from_mode, 0);
> 		  rtx from_imag
> 		    = simplify_gen_subreg (to_mode, XEXP (result, 1),
>-					   from_mode, 1);
>+					   from_mode, 0);
>+		  if (!from_real || !from_imag)
>+		    goto concat_store_slow;
> 		  emit_move_insn (XEXP (to_rtx, 0), from_real);
> 		  emit_move_insn (XEXP (to_rtx, 1), from_imag);
> 		}
>@@ -5167,14 +5169,35 @@ expand_assignment (tree to, tree from, b
> 		  rtx from_rtx
> 		    = simplify_gen_subreg (GET_MODE (to_rtx), result,
> 					   TYPE_MODE (TREE_TYPE (from)), 0);
>-		  emit_move_insn (XEXP (to_rtx, 0),
>-				  read_complex_part (from_rtx, false));
>-		  emit_move_insn (XEXP (to_rtx, 1),
>-				  read_complex_part (from_rtx, true));
>+		  if (from_rtx)
>+		    {
>+		      emit_move_insn (XEXP (to_rtx, 0),
>+				      read_complex_part (from_rtx, false));
>+		      emit_move_insn (XEXP (to_rtx, 1),
>+				      read_complex_part (from_rtx, true));
>+		    }
>+		  else
>+		    {
>+		      machine_mode to_mode
>+			= GET_MODE_INNER (GET_MODE (to_rtx));
>+		      rtx from_real
>+			= simplify_gen_subreg (to_mode, result,
>+					       TYPE_MODE (TREE_TYPE (from)),
>+					       0);
>+		      rtx from_imag
>+			= simplify_gen_subreg (to_mode, result,
>+					       TYPE_MODE (TREE_TYPE (from)),
>+					       GET_MODE_SIZE (to_mode));
>+		      if (!from_real || !from_imag)
>+			goto concat_store_slow;
>+		      emit_move_insn (XEXP (to_rtx, 0), from_real);
>+		      emit_move_insn (XEXP (to_rtx, 1), from_imag);
>+		    }
> 		}
> 	    }
> 	  else
> 	    {
>+	    concat_store_slow:;
> 	      rtx temp = assign_stack_temp (GET_MODE (to_rtx),
> 					    GET_MODE_SIZE (GET_MODE (to_rtx)));
> 	      write_complex_part (temp, XEXP (to_rtx, 0), false);
>--- gcc/testsuite/gcc.dg/pr83609.c.jj	2017-12-30 13:47:49.350044674
>+0100
>+++ gcc/testsuite/gcc.dg/pr83609.c	2017-12-30 13:42:52.227002619 +0100
>@@ -0,0 +1,29 @@
>+/* PR middle-end/83609 */
>+/* { dg-do run } */
>+/* { dg-options "-O2 -fno-tree-forwprop -fno-tree-ccp -fno-tree-fre
>-fno-tree-pre -fno-code-hoisting" } */
>+
>+#if __SIZEOF_LONG_LONG__ == 2 * __SIZEOF_FLOAT__
>+_Complex float
>+foo (void)
>+{
>+  _Complex float c;
>+  *((unsigned long long *)&c) = 0x123456789abcdef0ULL;
>+  return c;
>+}
>+
>+int
>+main ()
>+{
>+  union { _Complex float c; unsigned long long l; } u;
>+  u.c = foo ();
>+  if (u.l != 0x123456789abcdef0ULL)
>+    __builtin_abort ();
>+  return 0;
>+}
>+#else
>+int
>+main ()
>+{
>+  return 0;
>+}
>+#endif
>--- gcc/testsuite/g++.dg/opt/pr83609.C.jj	2017-12-30 13:48:18.937048860
>+0100
>+++ gcc/testsuite/g++.dg/opt/pr83609.C	2017-12-30 13:46:25.968032868
>+0100
>@@ -0,0 +1,28 @@
>+// PR middle-end/83609
>+// { dg-do compile }
>+// { dg-options "-O2 -fno-tree-forwprop" }
>+
>+template <typename> class B;
>+template <> struct B<float>
>+{
>+  float foo () { return __real__ b; }
>+  _Complex float b;
>+};
>+
>+void bar (int);
>+
>+template <class T>
>+void
>+baz ()
>+{
>+  B<T> h;
>+  T *a = (T *) &h;
>+  a[0] = a[1] = 6;
>+  h.foo () ? void () : bar (7);
>+}
>+
>+int
>+main ()
>+{
>+  baz<float> ();
>+}
>
>	Jakub
diff mbox series

Patch

--- gcc/expr.c.jj	2017-12-21 09:43:19.797042465 +0100
+++ gcc/expr.c	2017-12-30 13:49:19.634057445 +0100
@@ -5158,7 +5158,9 @@  expand_assignment (tree to, tree from, b
 					   from_mode, 0);
 		  rtx from_imag
 		    = simplify_gen_subreg (to_mode, XEXP (result, 1),
-					   from_mode, 1);
+					   from_mode, 0);
+		  if (!from_real || !from_imag)
+		    goto concat_store_slow;
 		  emit_move_insn (XEXP (to_rtx, 0), from_real);
 		  emit_move_insn (XEXP (to_rtx, 1), from_imag);
 		}
@@ -5167,14 +5169,35 @@  expand_assignment (tree to, tree from, b
 		  rtx from_rtx
 		    = simplify_gen_subreg (GET_MODE (to_rtx), result,
 					   TYPE_MODE (TREE_TYPE (from)), 0);
-		  emit_move_insn (XEXP (to_rtx, 0),
-				  read_complex_part (from_rtx, false));
-		  emit_move_insn (XEXP (to_rtx, 1),
-				  read_complex_part (from_rtx, true));
+		  if (from_rtx)
+		    {
+		      emit_move_insn (XEXP (to_rtx, 0),
+				      read_complex_part (from_rtx, false));
+		      emit_move_insn (XEXP (to_rtx, 1),
+				      read_complex_part (from_rtx, true));
+		    }
+		  else
+		    {
+		      machine_mode to_mode
+			= GET_MODE_INNER (GET_MODE (to_rtx));
+		      rtx from_real
+			= simplify_gen_subreg (to_mode, result,
+					       TYPE_MODE (TREE_TYPE (from)),
+					       0);
+		      rtx from_imag
+			= simplify_gen_subreg (to_mode, result,
+					       TYPE_MODE (TREE_TYPE (from)),
+					       GET_MODE_SIZE (to_mode));
+		      if (!from_real || !from_imag)
+			goto concat_store_slow;
+		      emit_move_insn (XEXP (to_rtx, 0), from_real);
+		      emit_move_insn (XEXP (to_rtx, 1), from_imag);
+		    }
 		}
 	    }
 	  else
 	    {
+	    concat_store_slow:;
 	      rtx temp = assign_stack_temp (GET_MODE (to_rtx),
 					    GET_MODE_SIZE (GET_MODE (to_rtx)));
 	      write_complex_part (temp, XEXP (to_rtx, 0), false);
--- gcc/testsuite/gcc.dg/pr83609.c.jj	2017-12-30 13:47:49.350044674 +0100
+++ gcc/testsuite/gcc.dg/pr83609.c	2017-12-30 13:42:52.227002619 +0100
@@ -0,0 +1,29 @@ 
+/* PR middle-end/83609 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-tree-forwprop -fno-tree-ccp -fno-tree-fre -fno-tree-pre -fno-code-hoisting" } */
+
+#if __SIZEOF_LONG_LONG__ == 2 * __SIZEOF_FLOAT__
+_Complex float
+foo (void)
+{
+  _Complex float c;
+  *((unsigned long long *)&c) = 0x123456789abcdef0ULL;
+  return c;
+}
+
+int
+main ()
+{
+  union { _Complex float c; unsigned long long l; } u;
+  u.c = foo ();
+  if (u.l != 0x123456789abcdef0ULL)
+    __builtin_abort ();
+  return 0;
+}
+#else
+int
+main ()
+{
+  return 0;
+}
+#endif
--- gcc/testsuite/g++.dg/opt/pr83609.C.jj	2017-12-30 13:48:18.937048860 +0100
+++ gcc/testsuite/g++.dg/opt/pr83609.C	2017-12-30 13:46:25.968032868 +0100
@@ -0,0 +1,28 @@ 
+// PR middle-end/83609
+// { dg-do compile }
+// { dg-options "-O2 -fno-tree-forwprop" }
+
+template <typename> class B;
+template <> struct B<float>
+{
+  float foo () { return __real__ b; }
+  _Complex float b;
+};
+
+void bar (int);
+
+template <class T>
+void
+baz ()
+{
+  B<T> h;
+  T *a = (T *) &h;
+  a[0] = a[1] = 6;
+  h.foo () ? void () : bar (7);
+}
+
+int
+main ()
+{
+  baz<float> ();
+}