https://gcc.gnu.org/g:24c5a3e5e8deb920c5d75f1125a0cf06b5b6aa63

commit r16-7035-g24c5a3e5e8deb920c5d75f1125a0cf06b5b6aa63
Author: Tamar Christina <[email protected]>
Date:   Mon Jan 26 08:06:34 2026 +0000

    vect: distinguish between MASK_CALL and non-trapping calls [PR123628]
    
    In the Fix for PR122103 an ambiguity was introduced when it comes to fortran
    due to an inconsistency in libmvec headers.
    
    A reproducer is
    
    !GCC$ builtin (expf) attributes simd (notinbranch)
    SUBROUTINE a(b)
       REAL, DIMENSION(:) :: b
       c: DO i = 1, d
       IF (e <= f) THEN
          g = EXP(h)
          r = g
          IF (r > s) THEN
             b(i) = t
          END IF
       END IF
       END DO c
    END
    
    compiled with -O2 -march=armv8-a+sve, note that fortran, unlike C provides 
the
    libmvec header math-vector-fortran.h unconditionally, which is a separate 
bug
    PR118955 which causes the functions to become available outside of -Ofast.
    
    This means the cases for MASK_CALL and trapping math overlap for fortran at 
-O2.
    
    The new masking code shouldn't handle SIMD clones.
    
    gcc/ChangeLog:
    
            PR tree-optimization/122103
            PR tree-optimization/123628
            * tree-if-conv.cc (if_convertible_simdclone_stmt_p): New.
            (if_convertible_stmt_p, predicate_statements): Use it.
    
    gcc/testsuite/ChangeLog:
    
            PR tree-optimization/122103
            PR tree-optimization/123628
            * gfortran.target/aarch64/pr123628.f90: New test.

Diff:
---
 gcc/testsuite/gfortran.target/aarch64/pr123628.f90 | 16 +++++++
 gcc/tree-if-conv.cc                                | 53 +++++++++++++++-------
 2 files changed, 53 insertions(+), 16 deletions(-)

diff --git a/gcc/testsuite/gfortran.target/aarch64/pr123628.f90 
b/gcc/testsuite/gfortran.target/aarch64/pr123628.f90
new file mode 100644
index 000000000000..5a42434890c3
--- /dev/null
+++ b/gcc/testsuite/gfortran.target/aarch64/pr123628.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+! { dg-options "-O2 -march=armv9-a -fdump-tree-ifcvt -w" }
+! { dg-final { scan-tree-dump {.MASK_CALL \(__builtin_expf, } ifcvt } }
+!GCC$ builtin (expf) attributes simd (notinbranch)
+SUBROUTINE a(b)
+   REAL, DIMENSION(:) :: b
+   c: DO i = 1, d
+   IF (e <= f) THEN
+      g = EXP(h)
+      r = g
+      IF (r > s) THEN
+         b(i) = t
+      END IF
+   END IF
+   END DO c
+END
diff --git a/gcc/tree-if-conv.cc b/gcc/tree-if-conv.cc
index 51fbcc128c67..d728f7c5221c 100644
--- a/gcc/tree-if-conv.cc
+++ b/gcc/tree-if-conv.cc
@@ -1120,6 +1120,36 @@ if_convertible_switch_p (gswitch *sw)
   return true;
 }
 
+/* Return true when STMT is an if-convertible SIMD clone stmts.
+
+   A SIMD clone statement is if-convertible if:
+    - it is an GIMPLE_CALL,
+    - it has a FNDECL,
+    - it has SIMD clones,
+    - it has at least one inbranch clone.  */
+static bool
+if_convertible_simdclone_stmt_p (gimple *stmt)
+{
+  if (!is_gimple_call (stmt))
+    return false;
+
+  tree fndecl = gimple_call_fndecl (stmt);
+  if (fndecl)
+    {
+      /* We can vectorize some builtins and functions with SIMD "inbranch"
+        clones.  */
+      struct cgraph_node *node = cgraph_node::get (fndecl);
+      if (node && node->simd_clones != NULL)
+       /* Ensure that at least one clone can be "inbranch".  */
+       for (struct cgraph_node *n = node->simd_clones; n != NULL;
+            n = n->simdclone->next_clone)
+         if (n->simdclone->inbranch)
+           return true;
+    }
+
+  return false;
+}
+
 /* Return true when STMT is if-convertible.
 
    A statement is if-convertible if:
@@ -1147,22 +1177,12 @@ if_convertible_stmt_p (gimple *stmt, 
vec<data_reference_p> refs)
 
     case GIMPLE_CALL:
       {
-       tree fndecl = gimple_call_fndecl (stmt);
-       if (fndecl)
+       /* Check if stmt is a simd clone first.  */
+       if (if_convertible_simdclone_stmt_p (stmt))
          {
-           /* We can vectorize some builtins and functions with SIMD
-              "inbranch" clones.  */
-           struct cgraph_node *node = cgraph_node::get (fndecl);
-           if (node && node->simd_clones != NULL)
-             /* Ensure that at least one clone can be "inbranch".  */
-             for (struct cgraph_node *n = node->simd_clones; n != NULL;
-                  n = n->simdclone->next_clone)
-               if (n->simdclone->inbranch)
-                 {
-                   gimple_set_plf (stmt, GF_PLF_2, true);
-                   need_to_predicate = true;
-                   return true;
-                 }
+           gimple_set_plf (stmt, GF_PLF_2, true);
+           need_to_predicate = true;
+           return true;
          }
 
        /* Check if the call can trap and if so require predication.  */
@@ -3108,7 +3128,8 @@ predicate_statements (loop_p loop)
            }
          else if (gimple_plf (stmt, GF_PLF_2)
                   && (is_gimple_assign (stmt)
-                      || gimple_call_builtin_p (stmt)))
+                      || (gimple_call_builtin_p (stmt)
+                          && !if_convertible_simdclone_stmt_p (stmt))))
            {
              tree lhs = gimple_get_lhs (stmt);
              /* ?? Assume that calls without an LHS are not data processing

Reply via email to