https://gcc.gnu.org/g:486c6296ed318d0df27a053d2288b6f4fa47517d

commit r17-4989-g486c6296ed318d0df27a053d2288b6f4fa47517d
Author: Kyrylo Tkachov <[email protected]>
Date:   Wed Oct 7 17:29:35 2026 +0200

    simplify-rtx: Fix ICE in the VEC_CONCAT halves fold [PR127483]
    
    simplify_binary_operation_1 simplifies the concatenation of the two
    halves of an object to gen_lowpart of the object.  get_ref_base_and_offset
    can return any rtx as the object, such as an UNSPEC, but gen_lowpart
    asserts for an UNSPEC in another mode.
    
    For example, on AArch64 fwprop1 tries to propagate the result of an LD2
    into the operands of an ADDP for:
    
      uint8x8x2_t v = vld2_u8 (p);
      return vpadd_u8 (v.val[0], v.val[1]);
    
    The ADDP operands then contain:
    
      (vec_concat:V16QI
        (subreg:V8QI (unspec:V2x8QI [(mem:V2x8QI (reg:DI p))] UNSPEC_LD2_DREG) 
0)
        (subreg:V8QI (unspec:V2x8QI [(mem:V2x8QI (reg:DI p))] UNSPEC_LD2_DREG) 
8))
    
    and gen_lowpart (V16QImode, (unspec:V2x8QI ...)) fails the assert.  The
    x86_64 testcase in the PR reaches the fold through debug insns.
    
    Use rtl_hooks.gen_lowpart_no_emit, like the other simplifications in this
    file, and do not fold if it fails.  Unlike gen_lowpart, the hook also
    never emits instructions.
    
    Bootstrapped and tested on x86_64-pc-linux-gnu.
    
    gcc/ChangeLog:
    
            PR rtl-optimization/127483
            * simplify-rtx.cc (simplify_context::simplify_binary_operation_1)
            <case VEC_CONCAT>: Use rtl_hooks.gen_lowpart_no_emit rather than
            gen_lowpart, and do not fold if it fails.
    
    gcc/testsuite/ChangeLog:
    
            PR rtl-optimization/127483
            * gcc.dg/pr127483.c: New test.
            * gcc.target/aarch64/pr127483.c: Likewise.
            * gcc.target/aarch64/pr127483-be.c: Likewise.
    
    Signed-off-by: Kyrylo Tkachov <[email protected]>

Diff:
---
 gcc/simplify-rtx.cc                            |  6 +++++-
 gcc/testsuite/gcc.dg/pr127483.c                | 15 ++++++++++++++
 gcc/testsuite/gcc.target/aarch64/pr127483-be.c |  7 +++++++
 gcc/testsuite/gcc.target/aarch64/pr127483.c    | 28 ++++++++++++++++++++++++++
 4 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index 42838cf0cdb5..68c65afb326f 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -5681,7 +5681,11 @@ simplify_ashift:
                  && known_eq (offset, GET_MODE_SIZE (op0_mode))
                  && !side_effects_p (trueop0)
                  && !side_effects_p (trueop1))
-               return gen_lowpart (mode, base0);
+               {
+                 tem = rtl_hooks.gen_lowpart_no_emit (mode, base0);
+                 if (tem)
+                   return tem;
+               }
            }
        }
       }
diff --git a/gcc/testsuite/gcc.dg/pr127483.c b/gcc/testsuite/gcc.dg/pr127483.c
new file mode 100644
index 000000000000..b81683785fa2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr127483.c
@@ -0,0 +1,15 @@
+/* PR rtl-optimization/127483 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-Og -g" } */
+
+typedef __attribute__((__vector_size__(16))) __int128 W;
+
+long c;
+W g;
+
+void
+foo()
+{
+  W w = g << c;
+  (struct {W m;}){w};
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr127483-be.c 
b/gcc/testsuite/gcc.target/aarch64/pr127483-be.c
new file mode 100644
index 000000000000..ff7f9678c66d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr127483-be.c
@@ -0,0 +1,7 @@
+/* PR rtl-optimization/127483 */
+/* { dg-do compile } */
+/* { dg-require-effective-target aarch64_mbig_endian } */
+/* Avoid a dependence on big-endian C library headers.  */
+/* { dg-options "-O2 -mbig-endian -ffreestanding" } */
+
+#include "pr127483.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/pr127483.c 
b/gcc/testsuite/gcc.target/aarch64/pr127483.c
new file mode 100644
index 000000000000..7f8fd1d4d540
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr127483.c
@@ -0,0 +1,28 @@
+/* PR rtl-optimization/127483 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_neon.h>
+
+/* Pairwise additions of the two registers of a structure load.  */
+
+uint8x8_t
+addp_u8 (const uint8_t *p)
+{
+  uint8x8x2_t v = vld2_u8 (p);
+  return vpadd_u8 (v.val[0], v.val[1]);
+}
+
+uint8x8_t
+addp_u8_rev (const uint8_t *p)
+{
+  uint8x8x2_t v = vld2_u8 (p);
+  return vpadd_u8 (v.val[1], v.val[0]);
+}
+
+int32x2_t
+addp_s32 (const int32_t *p)
+{
+  int32x2x2_t v = vld2_s32 (p);
+  return vpadd_s32 (v.val[0], v.val[1]);
+}

Reply via email to