The following testcase

void f (float *__restrict c, int *__restrict d, int n)
{
    for (int i = 0; i < n; i++)
    {
      if (d[i] > 1000)
        c[i] = __builtin_sqrtf (c[i]);
    }
}

compiled with -O3 -march=armv9-a -fno-math-errno -ftrapping-math

vectorizes as:

f:
        cmp     w2, 0
        ble     .L1
        mov     x3, 0
        mov     w4, 1000
        whilelo p7.s, wzr, w2
        mov     z31.s, w4
        ptrue   p6.b, all
.L3:
        ld1w    z0.s, p7/z, [x1, x3, lsl 2]
        cmpgt   p7.s, p7/z, z0.s, z31.s
        ld1w    z30.s, p7/z, [x0, x3, lsl 2]
        fsqrt   z30.s, p6/m, z30.s
        st1w    z30.s, p7, [x0, x3, lsl 2]
        incw    x3
        whilelo p7.s, w3, w2
        b.any   .L3
.L1:
        ret

which is incorrect, fsqrt can raise FE exceptions and so should be masked on p7
as the inactive lanes can trigger incorrect FE errors as the code in the PR
demonstrates.

In GCC 13 this was partially addressed for instruction that got lowered to IFNs
through r13-5979-gb9c78605039f839f3c79ad8fca4f60ea9a5654ed but it never
addressed __builtin_math_fns.  Assuming the direction of travel in PR96373 is
still valid this extends the support.

While ERRNO trapping is controlled through flags, it looks like for trapping
math the calls and IFNs are not marked specifically.  Instead in
gimple_could_trap_p_1 through operation_could_trap_p we default to all floating
point operation could trap if flag_trapping_math.

This extends gimple_could_trap_p_1 to do the same for __builtin_math_fns but
exclude instructions that the standard says can't raise FEs.

Bootstrapped Regtested on aarch64-none-linux-gnu,
arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
-m32, -m64 and no issues.

Ok for master?

Thanks,
Tamar

gcc/ChangeLog:

        PR tree-optimization/122103
        * gimple.cc (gimple_could_trap_p_1): Handle __builtin_ calls.

---
diff --git a/gcc/gimple.cc b/gcc/gimple.cc
index 
b968a45aaa06000b5b487c21d04ae840575a1362..dd910643002ef1dc128f6b5216aea783f3019edc
 100644
--- a/gcc/gimple.cc
+++ b/gcc/gimple.cc
@@ -2406,14 +2406,32 @@ gimple_could_trap_p_1 (const gimple *s, bool 
include_mem, bool include_stores)
       return gimple_asm_volatile_p (as_a <const gasm *> (s));
 
     case GIMPLE_CALL:
-      if (gimple_call_internal_p (s))
-       return false;
-      t = gimple_call_fndecl (s);
-      /* Assume that indirect and calls to weak functions may trap.  */
-      if (!t || !DECL_P (t) || DECL_WEAK (t))
-       return true;
-      return false;
+      {
+       if (gimple_call_internal_p (s))
+         return false;
+       t = gimple_call_fndecl (s);
+       /* Assume that indirect and calls to weak functions may trap.  */
+       if (!t || !DECL_P (t) || DECL_WEAK (t))
+         return true;
 
+       /* Any floating point builtin operation could trap.  */
+       if (gimple_call_builtin_p (s))
+         {
+           if (fndecl_built_in_p (t, BUILT_IN_NORMAL))
+             switch (DECL_FUNCTION_CODE (t))
+               {
+               CASE_FLT_FN (BUILT_IN_COPYSIGN):
+               CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
+                 return false;
+               default:
+                 break;
+               }
+           tree type = TREE_TYPE (gimple_call_fntype (s));
+           bool fp_operation = FLOAT_TYPE_P (type);
+           return fp_operation && flag_trapping_math;
+         }
+       return false;
+      }
     case GIMPLE_ASSIGN:
       op = gimple_assign_rhs_code (s);
 


-- 
diff --git a/gcc/gimple.cc b/gcc/gimple.cc
index b968a45aaa06000b5b487c21d04ae840575a1362..dd910643002ef1dc128f6b5216aea783f3019edc 100644
--- a/gcc/gimple.cc
+++ b/gcc/gimple.cc
@@ -2406,14 +2406,32 @@ gimple_could_trap_p_1 (const gimple *s, bool include_mem, bool include_stores)
       return gimple_asm_volatile_p (as_a <const gasm *> (s));
 
     case GIMPLE_CALL:
-      if (gimple_call_internal_p (s))
-	return false;
-      t = gimple_call_fndecl (s);
-      /* Assume that indirect and calls to weak functions may trap.  */
-      if (!t || !DECL_P (t) || DECL_WEAK (t))
-	return true;
-      return false;
+      {
+	if (gimple_call_internal_p (s))
+	  return false;
+	t = gimple_call_fndecl (s);
+	/* Assume that indirect and calls to weak functions may trap.  */
+	if (!t || !DECL_P (t) || DECL_WEAK (t))
+	  return true;
 
+	/* Any floating point builtin operation could trap.  */
+	if (gimple_call_builtin_p (s))
+	  {
+	    if (fndecl_built_in_p (t, BUILT_IN_NORMAL))
+	      switch (DECL_FUNCTION_CODE (t))
+		{
+		CASE_FLT_FN (BUILT_IN_COPYSIGN):
+		CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
+		  return false;
+		default:
+		  break;
+		}
+	    tree type = TREE_TYPE (gimple_call_fntype (s));
+	    bool fp_operation = FLOAT_TYPE_P (type);
+	    return fp_operation && flag_trapping_math;
+	  }
+	return false;
+      }
     case GIMPLE_ASSIGN:
       op = gimple_assign_rhs_code (s);
 

Reply via email to