expand: Fix up expansion of VIEW_CONVERT_EXPR to BITINT_TYPE [PR117354]

Message ID ZyM4hED/3n1T+0VI@tucnak
State New
Headers
Series expand: Fix up expansion of VIEW_CONVERT_EXPR to BITINT_TYPE [PR117354] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 fail Patch failed to apply

Commit Message

Jakub Jelinek Oct. 31, 2024, 7:57 a.m. UTC
  Hi!

The following testcase ICEs, because when trying to expand the
VIEW_CONVERT_EXPR operand which is SSA_NAME defined to
V32QI or V4DI MEM_REF which is aligned just to 8 bytes we force
it as unaligned into a register, but then try to call extract_bit_field
from the V32QI or V4DI register to BLKmode.  extract_bit_field doesn't
obviously support BLKmode extraction and so ICEs.

The second hunk fixes the ICE by not calling extract_bit_field when
it can't handle it, the last if will handle it properly by storing
it to memory and using BLKmode access to the copy.

The first hunk is an optimization, if mode is BLKmode, by setting
inner_reference_p argument to expand_expr_real we avoid the
expand_misaligned_mem_ref calls which load it from memory into a register.

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

2024-10-31  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/117354
	* expr.cc (expand_expr_real_1) <case VIEW_CONVERT_EXPR>: Pass
	true as inner_reference_p argument to expand_expr_real if
	mode is BLKmode.  Don't call extract_bit_field if mode is BLKmode.

	* gcc.dg/bitint-113.c: New test.


	Jakub
  

Comments

Richard Biener Oct. 31, 2024, 8:12 a.m. UTC | #1
On Thu, 31 Oct 2024, Jakub Jelinek wrote:

> Hi!
> 
> The following testcase ICEs, because when trying to expand the
> VIEW_CONVERT_EXPR operand which is SSA_NAME defined to
> V32QI or V4DI MEM_REF which is aligned just to 8 bytes we force
> it as unaligned into a register, but then try to call extract_bit_field
> from the V32QI or V4DI register to BLKmode.  extract_bit_field doesn't
> obviously support BLKmode extraction and so ICEs.
> 
> The second hunk fixes the ICE by not calling extract_bit_field when
> it can't handle it, the last if will handle it properly by storing
> it to memory and using BLKmode access to the copy.
> 
> The first hunk is an optimization, if mode is BLKmode, by setting
> inner_reference_p argument to expand_expr_real we avoid the
> expand_misaligned_mem_ref calls which load it from memory into a register.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Thanks,
Richard.

> 2024-10-31  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR middle-end/117354
> 	* expr.cc (expand_expr_real_1) <case VIEW_CONVERT_EXPR>: Pass
> 	true as inner_reference_p argument to expand_expr_real if
> 	mode is BLKmode.  Don't call extract_bit_field if mode is BLKmode.
> 
> 	* gcc.dg/bitint-113.c: New test.
> 
> --- gcc/expr.cc.jj	2024-10-25 10:00:29.450768114 +0200
> +++ gcc/expr.cc	2024-10-30 14:16:58.624455194 +0100
> @@ -12468,7 +12468,7 @@ expand_expr_real_1 (tree exp, rtx target
>  
>        if (!op0)
>  	op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier,
> -				NULL, inner_reference_p);
> +				NULL, inner_reference_p || mode == BLKmode);
>  
>        /* If the input and output modes are both the same, we are done.  */
>        if (mode == GET_MODE (op0))
> @@ -12505,7 +12505,7 @@ expand_expr_real_1 (tree exp, rtx target
>  	op0 = convert_modes (mode, GET_MODE (op0), op0,
>  			     TYPE_UNSIGNED (TREE_TYPE (treeop0)));
>        /* If the output type is a bit-field type, do an extraction.  */
> -      else if (reduce_bit_field)
> +      else if (reduce_bit_field && mode != BLKmode)
>  	return extract_bit_field (op0, TYPE_PRECISION (type), 0,
>  				  TYPE_UNSIGNED (type), NULL_RTX,
>  				  mode, mode, false, NULL);
> --- gcc/testsuite/gcc.dg/bitint-113.c.jj	2024-10-30 14:32:39.153442458 +0100
> +++ gcc/testsuite/gcc.dg/bitint-113.c	2024-10-30 14:34:41.036768474 +0100
> @@ -0,0 +1,40 @@
> +/* PR middle-end/117354 */
> +/* { dg-do compile { target bitint } } */
> +/* { dg-options "-O2" } */
> +/* { dg-additional-options "-mavx2" { target x86_64-*-* i?86-*-* } } */
> +
> +#if __BITINT_MAXWIDTH__ >= 256
> +#define N 256
> +#else
> +#define N 64
> +#endif
> +
> +struct S {
> +  unsigned char y;
> +  _BitInt(N) x;
> +} s;
> +
> +__attribute__((noipa)) static void
> +foo (const char *, _BitInt(N))
> +{
> +}
> +
> +__attribute__((noipa)) static void
> +bar (_BitInt(N))
> +{
> +}
> +
> +static void
> +baz (void *p)
> +{
> +  foo ("bazbazbazb", s.x);
> +  __builtin_memcpy (p, &s.x, sizeof s.x);
> +}
> +
> +int
> +main ()
> +{
> +  void *ptr = &s.x;
> +  baz (&s.x);
> +  bar (*(_BitInt(N) *) ptr);
> +}
> 
> 	Jakub
> 
>
  

Patch

--- gcc/expr.cc.jj	2024-10-25 10:00:29.450768114 +0200
+++ gcc/expr.cc	2024-10-30 14:16:58.624455194 +0100
@@ -12468,7 +12468,7 @@  expand_expr_real_1 (tree exp, rtx target
 
       if (!op0)
 	op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier,
-				NULL, inner_reference_p);
+				NULL, inner_reference_p || mode == BLKmode);
 
       /* If the input and output modes are both the same, we are done.  */
       if (mode == GET_MODE (op0))
@@ -12505,7 +12505,7 @@  expand_expr_real_1 (tree exp, rtx target
 	op0 = convert_modes (mode, GET_MODE (op0), op0,
 			     TYPE_UNSIGNED (TREE_TYPE (treeop0)));
       /* If the output type is a bit-field type, do an extraction.  */
-      else if (reduce_bit_field)
+      else if (reduce_bit_field && mode != BLKmode)
 	return extract_bit_field (op0, TYPE_PRECISION (type), 0,
 				  TYPE_UNSIGNED (type), NULL_RTX,
 				  mode, mode, false, NULL);
--- gcc/testsuite/gcc.dg/bitint-113.c.jj	2024-10-30 14:32:39.153442458 +0100
+++ gcc/testsuite/gcc.dg/bitint-113.c	2024-10-30 14:34:41.036768474 +0100
@@ -0,0 +1,40 @@ 
+/* PR middle-end/117354 */
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-mavx2" { target x86_64-*-* i?86-*-* } } */
+
+#if __BITINT_MAXWIDTH__ >= 256
+#define N 256
+#else
+#define N 64
+#endif
+
+struct S {
+  unsigned char y;
+  _BitInt(N) x;
+} s;
+
+__attribute__((noipa)) static void
+foo (const char *, _BitInt(N))
+{
+}
+
+__attribute__((noipa)) static void
+bar (_BitInt(N))
+{
+}
+
+static void
+baz (void *p)
+{
+  foo ("bazbazbazb", s.x);
+  __builtin_memcpy (p, &s.x, sizeof s.x);
+}
+
+int
+main ()
+{
+  void *ptr = &s.x;
+  baz (&s.x);
+  bar (*(_BitInt(N) *) ptr);
+}