On Mon, 26 Jan 2026, Tamar Christina wrote:
> 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.
>
> Bootstrapped Regtested on aarch64-none-linux-gnu,
> arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
> -m32, -m64 and no issues.
>
> Pushed.
Thanks. Another possibility would have been to always create
a .MASK_CALL and leave checking/failure to the vectorizer. Of course
doing it in if-conversion will be better for compile time.
Richard.
> Thanks,
> Tamar
>
> 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 --git a/gcc/testsuite/gfortran.target/aarch64/pr123628.f90
> b/gcc/testsuite/gfortran.target/aarch64/pr123628.f90
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..5a42434890c332c7eb1619b84d9eac486fe89d86
> --- /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
> 51fbcc128c671d749bd97dfa91f6f4b605eb8f82..d728f7c5221c66c2fd963d3e3ab55b232e628cb0
> 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
>
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)