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
