https://gcc.gnu.org/g:82e4ddc02061b325735383c6cd4686a7d68230cf

commit r17-3884-g82e4ddc02061b325735383c6cd4686a7d68230cf
Author: Julio Sotoriva De Bastiani <[email protected]>
Date:   Tue Sep 1 10:22:05 2026 +0000

    aarch64: Fix folding for svwhilel*_c* builtins [PR126096]
    
    This fixes an ICE that occurred when trying to fold svwhilelt and
    svwhilele predicate-as-counter builtins as if they were
    predicate-as-mask builtins.
    
    gcc/ChangeLog:
    
            PR target/126096
            * config/aarch64/aarch64-acle-builtins.cc
            (gimple_folder::fold_to_pfalse): Handle svcount_t.
            * config/aarch64/aarch64-sve-builtins-base.cc
            (svpfalse_impl::fold): Handle svcount_t.
            (svwhilelx_impl::fold_type): Punt for non-pfalse svcount_t.
    
    gcc/testsuite/ChangeLog:
    
            PR target/126096
            * gcc.target/aarch64/sve2/acle/general/whilele_1.c: New test.
            * gcc.target/aarch64/sve2/acle/general/whilelt_1.c: New test.

Diff:
---
 gcc/config/aarch64/aarch64-acle-builtins.cc        | 11 +++-
 gcc/config/aarch64/aarch64-sve-builtins-base.cc    |  9 ++--
 .../aarch64/sve2/acle/general/whilele_1.c          | 61 ++++++++++++++++++++++
 .../aarch64/sve2/acle/general/whilelt_1.c          | 61 ++++++++++++++++++++++
 4 files changed, 137 insertions(+), 5 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-acle-builtins.cc 
b/gcc/config/aarch64/aarch64-acle-builtins.cc
index 98ba6c8d3472..b1a25d5cc4ed 100644
--- a/gcc/config/aarch64/aarch64-acle-builtins.cc
+++ b/gcc/config/aarch64/aarch64-acle-builtins.cc
@@ -3011,7 +3011,16 @@ gimple_folder::fold_to_ptrue ()
 gimple *
 gimple_folder::fold_to_pfalse ()
 {
-  return gimple_build_assign (lhs, build_zero_cst (TREE_TYPE (lhs)));
+  if (type_suffix (0).tclass == TYPE_bool)
+    return gimple_build_assign (lhs, build_zero_cst (TREE_TYPE (lhs)));
+
+  if (type_suffix (0).tclass == TYPE_count)
+    {
+      tree svbool_type = abi_vector_types[VECTOR_TYPE_svbool_t];
+      return fold_call_to (build_zero_cst (svbool_type));
+    }
+
+  return NULL;
 }
 
 /* Fold an operation to a constant predicate in which the first VL
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc 
b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
index bad2ccb2fd6e..dbd486edc515 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
@@ -2552,10 +2552,7 @@ public:
   gimple *
   fold (gimple_folder &f) const override
   {
-    if (f.type_suffix (0).tclass == TYPE_bool)
-      return f.fold_to_pfalse ();
-
-    return nullptr;
+    return f.fold_to_pfalse ();
   }
 
   rtx
@@ -3448,6 +3445,10 @@ public:
     if (m_eq_p ? known_gt (arg0, arg1) : known_ge (arg0, arg1))
       return f.fold_to_pfalse ();
 
+    /* Punt if we are trying to fold a predicate-as-counter builtin.  */
+    if (f.type_suffix (0).tclass == TYPE_count)
+      return NULL;
+
     /* Punt if we can't tell at compile time whether the result
        is all-false.  */
     if (m_eq_p ? maybe_gt (arg0, arg1) : maybe_ge (arg0, arg1))
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilele_1.c 
b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilele_1.c
new file mode 100644
index 000000000000..7e5905fd3c7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilele_1.c
@@ -0,0 +1,61 @@
+/* { dg-do compile { target { ! aarch64_asm_sve2p1_ok } } } */
+/* { dg-do assemble { target { aarch64_asm_sve2p1_ok } } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+#pragma GCC target "+sve2p1"
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+
+void
+test1 (svcount_t *ptr)
+{
+  *ptr = svwhilele_c8_s64 (0, -57, 2);
+}
+
+void
+test2 (svcount_t *ptr)
+{
+  *ptr = svwhilele_c8_u64 (50, 0, 2);
+}
+
+void
+test3 (svcount_t *ptr)
+{
+  *ptr = svwhilele_c16_s64 (7, 5, 2);
+}
+
+void
+test4 (svcount_t *ptr)
+{
+  *ptr = svwhilele_c16_u64 (900, 100, 2);
+}
+
+void
+test5 (svcount_t *ptr)
+{
+  *ptr = svwhilele_c32_s64 (-10, -50, 4);
+}
+
+void
+test6 (svcount_t *ptr)
+{
+  *ptr = svwhilele_c32_u64 (1, 0, 4);
+}
+
+void
+test7 (svcount_t *ptr)
+{
+  *ptr = svwhilele_c64_s64 (0, -5, 4);
+}
+
+void
+test8 (svcount_t *ptr)
+{
+  *ptr = svwhilele_c64_u64 (8, 0, 4);
+}
+
+/* { dg-final { scan-assembler-times {\tpfalse\tp[0-9]+\.b\n} 8 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilelt_1.c 
b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilelt_1.c
new file mode 100644
index 000000000000..ea70d7272b1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilelt_1.c
@@ -0,0 +1,61 @@
+/* { dg-do compile { target { ! aarch64_asm_sve2p1_ok } } } */
+/* { dg-do assemble { target { aarch64_asm_sve2p1_ok } } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+#pragma GCC target "+sve2p1"
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+
+void
+test1 (svcount_t *ptr)
+{
+  *ptr = svwhilelt_c8_s64 (0, -57, 2);
+}
+
+void
+test2 (svcount_t *ptr)
+{
+  *ptr = svwhilelt_c8_u64 (50, 0, 2);
+}
+
+void
+test3 (svcount_t *ptr)
+{
+  *ptr = svwhilelt_c16_s64 (0, 0, 2);
+}
+
+void
+test4 (svcount_t *ptr)
+{
+  *ptr = svwhilelt_c16_u64 (0, 0, 2);
+}
+
+void
+test5 (svcount_t *ptr)
+{
+  *ptr = svwhilelt_c32_s64 (-10, -50, 4);
+}
+
+void
+test6 (svcount_t *ptr)
+{
+  *ptr = svwhilelt_c32_u64 (0, 0, 4);
+}
+
+void
+test7 (svcount_t *ptr)
+{
+  *ptr = svwhilelt_c64_s64 (0, 0, 4);
+}
+
+void
+test8 (svcount_t *ptr)
+{
+  *ptr = svwhilelt_c64_u64 (0, 0, 4);
+}
+
+/* { dg-final { scan-assembler-times {\tpfalse\tp[0-9]+\.b\n} 8 } } */

Reply via email to