https://gcc.gnu.org/g:b39f62ff739e9ffea0e6485667f15b985f8cd63d

commit r15-4796-gb39f62ff739e9ffea0e6485667f15b985f8cd63d
Author: Jakub Jelinek <[email protected]>
Date:   Thu Oct 31 10:52:56 2024 +0100

    expand: Fix up expansion of VIEW_CONVERT_EXPR to BITINT_TYPE [PR117354]
    
    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.
    
    2024-10-31  Jakub Jelinek  <[email protected]>
    
            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.

Diff:
---
 gcc/expr.cc                       |  4 ++--
 gcc/testsuite/gcc.dg/bitint-113.c | 40 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/gcc/expr.cc b/gcc/expr.cc
index 348ac3c777a3..caa1a72ba0be 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -12468,7 +12468,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode 
tmode,
 
       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, machine_mode 
tmode,
        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);
diff --git a/gcc/testsuite/gcc.dg/bitint-113.c 
b/gcc/testsuite/gcc.dg/bitint-113.c
new file mode 100644
index 000000000000..3c934a62fb47
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/bitint-113.c
@@ -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);
+}

Reply via email to