]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
vect: distinguish between MASK_CALL and non-trapping calls [PR123628]
authorTamar Christina <tamar.christina@arm.com>
Mon, 26 Jan 2026 08:06:34 +0000 (08:06 +0000)
committerTamar Christina <tamar.christina@arm.com>
Mon, 26 Jan 2026 08:06:34 +0000 (08:06 +0000)
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.

gcc/testsuite/gfortran.target/aarch64/pr123628.f90 [new file with mode: 0644]
gcc/tree-if-conv.cc

diff --git a/gcc/testsuite/gfortran.target/aarch64/pr123628.f90 b/gcc/testsuite/gfortran.target/aarch64/pr123628.f90
new file mode 100644 (file)
index 0000000..5a42434
--- /dev/null
@@ -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
index 51fbcc128c671d749bd97dfa91f6f4b605eb8f82..d728f7c5221c66c2fd963d3e3ab55b232e628cb0 100644 (file)
@@ -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