public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix ICE during MEM_REF expansion (PR middle-end/90840)
@ 2019-11-19 23:46 Jakub Jelinek
  2019-11-20  2:39 ` Jeff Law
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jakub Jelinek @ 2019-11-19 23:46 UTC (permalink / raw)
  To: Richard Biener, Jeff Law; +Cc: gcc-patches

Hi!

On the following testcase we ICE on i686-linux (32-bit), because we store
(first 96-bit, then 72-bit) structure into the first part of a 2x 96-bit
complex long double, and for 96-bit floats there is no corresponding
integral mode that covers it and we ICE when op0 is not in MEM (it is a
REG).
The following patch handles the simple case where the whole dest REG is
covered and value is a MEM using a load from the memory, and for the rest
just spills on the stack, similarly how we punt when for stores to complex
REGs if the bitsize/bitnum cover portions of both halves.

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

2019-11-19  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/90840
	* expmed.c (store_bit_field_1): Handle the case where op0 is not a MEM
	and has a mode that doesn't have corresponding integral type.

	* gcc.c-torture/compile/pr90840.c: New test.

--- gcc/expmed.c.jj	2019-11-15 00:37:32.000000000 +0100
+++ gcc/expmed.c	2019-11-19 17:09:22.035129617 +0100
@@ -840,6 +840,27 @@ store_bit_field_1 (rtx str_rtx, poly_uin
       if (MEM_P (op0))
 	op0 = adjust_bitfield_address_size (op0, op0_mode.else_blk (),
 					    0, MEM_SIZE (op0));
+      else if (!op0_mode.exists ())
+	{
+	  if (ibitnum == 0
+	      && known_eq (ibitsize, GET_MODE_BITSIZE (GET_MODE (op0)))
+	      && MEM_P (value)
+	      && !reverse)
+	    {
+	      value = adjust_address (value, GET_MODE (op0), 0);
+	      emit_move_insn (op0, value);
+	      return true;
+	    }
+	  if (!fallback_p)
+	    return false;
+	  rtx temp = assign_stack_temp (GET_MODE (op0),
+					GET_MODE_SIZE (GET_MODE (op0)));
+	  emit_move_insn (temp, op0);
+	  store_bit_field_1 (temp, bitsize, bitnum, 0, 0, fieldmode, value,
+			     reverse, fallback_p);
+	  emit_move_insn (op0, temp);
+	  return true;
+	}
       else
 	op0 = gen_lowpart (op0_mode.require (), op0);
     }
--- gcc/testsuite/gcc.c-torture/compile/pr90840.c.jj	2019-11-19 17:18:31.361918896 +0100
+++ gcc/testsuite/gcc.c-torture/compile/pr90840.c	2019-11-19 17:11:06.010575339 +0100
@@ -0,0 +1,19 @@
+/* PR middle-end/90840 */
+struct S { long long a; int b; };
+struct S foo (void);
+struct __attribute__((packed)) T { long long a; char b; };
+struct T baz (void);
+
+void
+bar (void)
+{
+  _Complex long double c;
+  *(struct S *) &c = foo ();
+}
+
+void
+qux (void)
+{
+  _Complex long double c;
+  *(struct T *) &c = baz ();
+}

	Jakub

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Fix ICE during MEM_REF expansion (PR middle-end/90840)
  2019-11-19 23:46 [PATCH] Fix ICE during MEM_REF expansion (PR middle-end/90840) Jakub Jelinek
@ 2019-11-20  2:39 ` Jeff Law
  2019-11-20  7:30 ` Richard Biener
  2019-12-07 12:21 ` Eric Botcazou
  2 siblings, 0 replies; 4+ messages in thread
From: Jeff Law @ 2019-11-20  2:39 UTC (permalink / raw)
  To: Jakub Jelinek, Richard Biener; +Cc: gcc-patches

On 11/19/19 4:42 PM, Jakub Jelinek wrote:
> Hi!
> 
> On the following testcase we ICE on i686-linux (32-bit), because we store
> (first 96-bit, then 72-bit) structure into the first part of a 2x 96-bit
> complex long double, and for 96-bit floats there is no corresponding
> integral mode that covers it and we ICE when op0 is not in MEM (it is a
> REG).
> The following patch handles the simple case where the whole dest REG is
> covered and value is a MEM using a load from the memory, and for the rest
> just spills on the stack, similarly how we punt when for stores to complex
> REGs if the bitsize/bitnum cover portions of both halves.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2019-11-19  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR middle-end/90840
> 	* expmed.c (store_bit_field_1): Handle the case where op0 is not a MEM
> 	and has a mode that doesn't have corresponding integral type.
> 
> 	* gcc.c-torture/compile/pr90840.c: New test.
OK
jeff

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Fix ICE during MEM_REF expansion (PR middle-end/90840)
  2019-11-19 23:46 [PATCH] Fix ICE during MEM_REF expansion (PR middle-end/90840) Jakub Jelinek
  2019-11-20  2:39 ` Jeff Law
@ 2019-11-20  7:30 ` Richard Biener
  2019-12-07 12:21 ` Eric Botcazou
  2 siblings, 0 replies; 4+ messages in thread
From: Richard Biener @ 2019-11-20  7:30 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Jeff Law, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2796 bytes --]

On Wed, 20 Nov 2019, Jakub Jelinek wrote:

> Hi!
> 
> On the following testcase we ICE on i686-linux (32-bit), because we store
> (first 96-bit, then 72-bit) structure into the first part of a 2x 96-bit
> complex long double, and for 96-bit floats there is no corresponding
> integral mode that covers it and we ICE when op0 is not in MEM (it is a
> REG).
> The following patch handles the simple case where the whole dest REG is
> covered and value is a MEM using a load from the memory, and for the rest
> just spills on the stack, similarly how we punt when for stores to complex
> REGs if the bitsize/bitnum cover portions of both halves.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Richard.

> 2019-11-19  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR middle-end/90840
> 	* expmed.c (store_bit_field_1): Handle the case where op0 is not a MEM
> 	and has a mode that doesn't have corresponding integral type.
> 
> 	* gcc.c-torture/compile/pr90840.c: New test.
> 
> --- gcc/expmed.c.jj	2019-11-15 00:37:32.000000000 +0100
> +++ gcc/expmed.c	2019-11-19 17:09:22.035129617 +0100
> @@ -840,6 +840,27 @@ store_bit_field_1 (rtx str_rtx, poly_uin
>        if (MEM_P (op0))
>  	op0 = adjust_bitfield_address_size (op0, op0_mode.else_blk (),
>  					    0, MEM_SIZE (op0));
> +      else if (!op0_mode.exists ())
> +	{
> +	  if (ibitnum == 0
> +	      && known_eq (ibitsize, GET_MODE_BITSIZE (GET_MODE (op0)))
> +	      && MEM_P (value)
> +	      && !reverse)
> +	    {
> +	      value = adjust_address (value, GET_MODE (op0), 0);
> +	      emit_move_insn (op0, value);
> +	      return true;
> +	    }
> +	  if (!fallback_p)
> +	    return false;
> +	  rtx temp = assign_stack_temp (GET_MODE (op0),
> +					GET_MODE_SIZE (GET_MODE (op0)));
> +	  emit_move_insn (temp, op0);
> +	  store_bit_field_1 (temp, bitsize, bitnum, 0, 0, fieldmode, value,
> +			     reverse, fallback_p);
> +	  emit_move_insn (op0, temp);
> +	  return true;
> +	}
>        else
>  	op0 = gen_lowpart (op0_mode.require (), op0);
>      }
> --- gcc/testsuite/gcc.c-torture/compile/pr90840.c.jj	2019-11-19 17:18:31.361918896 +0100
> +++ gcc/testsuite/gcc.c-torture/compile/pr90840.c	2019-11-19 17:11:06.010575339 +0100
> @@ -0,0 +1,19 @@
> +/* PR middle-end/90840 */
> +struct S { long long a; int b; };
> +struct S foo (void);
> +struct __attribute__((packed)) T { long long a; char b; };
> +struct T baz (void);
> +
> +void
> +bar (void)
> +{
> +  _Complex long double c;
> +  *(struct S *) &c = foo ();
> +}
> +
> +void
> +qux (void)
> +{
> +  _Complex long double c;
> +  *(struct T *) &c = baz ();
> +}
> 
> 	Jakub
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Fix ICE during MEM_REF expansion (PR middle-end/90840)
  2019-11-19 23:46 [PATCH] Fix ICE during MEM_REF expansion (PR middle-end/90840) Jakub Jelinek
  2019-11-20  2:39 ` Jeff Law
  2019-11-20  7:30 ` Richard Biener
@ 2019-12-07 12:21 ` Eric Botcazou
  2 siblings, 0 replies; 4+ messages in thread
From: Eric Botcazou @ 2019-12-07 12:21 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches, Richard Biener, Jeff Law

[-- Attachment #1: Type: text/plain, Size: 1553 bytes --]

> On the following testcase we ICE on i686-linux (32-bit), because we store
> (first 96-bit, then 72-bit) structure into the first part of a 2x 96-bit
> complex long double, and for 96-bit floats there is no corresponding
> integral mode that covers it and we ICE when op0 is not in MEM (it is a
> REG).

The test triggers an ICE in simplify_subreg because the innermode is BLKmode:

  gcc_assert (innermode != BLKmode);

on PowerPC64/VxWorks at -O1 and above.  This comes from this call:

		  if (MEM_P (result))
 		    from_rtx = change_address (result, to_mode, NULL_RTX);
 		  else
 		    from_rtx
		      = simplify_gen_subreg (to_mode, result,
					     TYPE_MODE (TREE_TYPE (from)), 0);

in expand_assignment, where 'result' is not a MEM despite TREE_TYPE (from) 
having BLKmode.  That's as expected because 'from' is a CALL_EXPR whose result 
is returned as a TImode register to avoid using BLKmode and thus spilling it 
to memory in between.

It turns out that simplify_subreg contains another assertion:

  gcc_assert (GET_MODE (op) == innermode
	      || GET_MODE (op) == VOIDmode);

so we can equivalently pass GET_MODE (result) as the mode, except when it is 
VOIDmode in which case we can still use TYPE_MODE (TREE_TYPE (from)).

Tested on PowerPC64/VxWorks and x86-64/Linux, applied on mainline as obvious.


2019-12-07  Eric Botcazou  <ebotcazou@adacore.com>

	PR middle-end/90840
	* expr.c (expand_assignment): In the case of a CONCAT on the LHS, make
	sure to pass a valid inner mode in calls to simplify_gen_subreg.

-- 
Eric Botcazou

[-- Attachment #2: p.diff --]
[-- Type: text/x-patch, Size: 1298 bytes --]

Index: expr.c
===================================================================
--- expr.c	(revision 278938)
+++ expr.c	(working copy)
@@ -5285,13 +5285,16 @@ expand_assignment (tree to, tree from, b
 		}
 	      else
 		{
+		  machine_mode from_mode
+		    = GET_MODE (result) == VOIDmode
+		      ? TYPE_MODE (TREE_TYPE (from))
+		      : GET_MODE (result);
 		  rtx from_rtx;
 		  if (MEM_P (result))
 		    from_rtx = change_address (result, to_mode, NULL_RTX);
 		  else
 		    from_rtx
-		      = simplify_gen_subreg (to_mode, result,
-					     TYPE_MODE (TREE_TYPE (from)), 0);
+		      = simplify_gen_subreg (to_mode, result, from_mode, 0);
 		  if (from_rtx)
 		    {
 		      emit_move_insn (XEXP (to_rtx, 0),
@@ -5303,12 +5306,9 @@ expand_assignment (tree to, tree from, b
 		    {
 		      to_mode = GET_MODE_INNER (to_mode);
 		      rtx from_real
-			= simplify_gen_subreg (to_mode, result,
-					       TYPE_MODE (TREE_TYPE (from)),
-					       0);
+			= simplify_gen_subreg (to_mode, result, from_mode, 0);
 		      rtx from_imag
-			= simplify_gen_subreg (to_mode, result,
-					       TYPE_MODE (TREE_TYPE (from)),
+			= simplify_gen_subreg (to_mode, result, from_mode,
 					       GET_MODE_SIZE (to_mode));
 		      if (!from_real || !from_imag)
 			goto concat_store_slow;

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-12-07 12:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-19 23:46 [PATCH] Fix ICE during MEM_REF expansion (PR middle-end/90840) Jakub Jelinek
2019-11-20  2:39 ` Jeff Law
2019-11-20  7:30 ` Richard Biener
2019-12-07 12:21 ` Eric Botcazou

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).