> -----Original Message-----
> From: Richard Biener <[email protected]>
> Sent: 26 January 2026 08:11
> To: Tamar Christina <[email protected]>
> Cc: [email protected]; nd <[email protected]>; [email protected]
> Subject: Re: [PATCH][vect]: distinguish between MASK_CALL and non-
> trapping calls [PR123628]
>
> 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.
>
True, I need to extend this in GCC 17 anyway to support masking arbitrary
builtins to support HVLA, so .MASK_CALL as a default fall back would be
good. But as you say rejecting them early on e.g. (Adv. SIMD can't do masking)
can save a lot of time :).
Thanks,
Tamar
> 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..5a42434890c332c7eb
> 1619b84d9eac486fe89d86
> > --- /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..d728f7c5221c66c2fd963d
> 3e3ab55b232e628cb0 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)