[gcc r16-7035] vect: distinguish between MASK_CALL and non-trapping calls [PR123628]

Tamar Christina tnfchris@gcc.gnu.org
Mon Jan 26 08:07:26 GMT 2026


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

commit r16-7035-g24c5a3e5e8deb920c5d75f1125a0cf06b5b6aa63
Author: Tamar Christina <tamar.christina@arm.com>
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


More information about the Gcc-cvs mailing list