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  <ja...@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 <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)

Reply via email to