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)

Reply via email to