builtin fe[gs]etround

Marc Glisse marc.glisse@inria.fr
Sun Feb 23 11:09:00 GMT 2014


Hello,

a natural first step to optimize changes of rounding modes seems to be 
making these 2 functions builtins. I don't know exactly how far 
optimizations will be able to go (the fact that fesetround can fail 
complicates things a lot). What is included here:

1) fegetround is pure.

2) Neither function aliases (use or clobber) any memory. I expect this is 
likely not true on all platforms, some probably store the rounding mode in 
a global variable that is accessible through other means (though mixing 
direct accesses with calls to fe*etround seems a questionable style). Any 
opinion or advice here?

Regtested on x86_64-linux-gnu, certainly not for 4.9.

2014-02-23  Marc Glisse  <marc.glisse@inria.fr>

gcc/
 	* builtins.def (BUILT_IN_FEGETROUND, BUILT_IN_FESETROUND): Add.
 	* tree-ssa-alias.c (ref_maybe_used_by_call_p_1,
 	call_may_clobber_ref_p_1): Handle them.

gcc/testsuite/
 	* gcc.dg/tree-ssa/fegsetround.c: New file.

-- 
Marc Glisse
-------------- next part --------------
Index: gcc/builtins.def
===================================================================
--- gcc/builtins.def	(revision 208045)
+++ gcc/builtins.def	(working copy)
@@ -276,20 +276,22 @@ DEF_C99_BUILTIN        (BUILT_IN_EXPM1F,
 DEF_C99_BUILTIN        (BUILT_IN_EXPM1L, "expm1l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_LIB_BUILTIN        (BUILT_IN_FABS, "fabs", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_FABSF, "fabsf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_FABSL, "fabsl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_FABSD32, "fabsd32", BT_FN_DFLOAT32_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_FABSD64, "fabsd64", BT_FN_DFLOAT64_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_FABSD128, "fabsd128", BT_FN_DFLOAT128_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_FDIM, "fdim", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_BUILTIN        (BUILT_IN_FDIMF, "fdimf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_BUILTIN        (BUILT_IN_FDIML, "fdiml", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN        (BUILT_IN_FEGETROUND, "fegetround", BT_FN_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN        (BUILT_IN_FESETROUND, "fesetround", BT_FN_INT_INT, ATTR_NOTHROW_LEAF_LIST)
 DEF_LIB_BUILTIN        (BUILT_IN_FLOOR, "floor", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_FLOORF, "floorf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_FLOORL, "floorl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_FMA, "fma", BT_FN_DOUBLE_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
 DEF_C99_BUILTIN        (BUILT_IN_FMAF, "fmaf", BT_FN_FLOAT_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
 DEF_C99_BUILTIN        (BUILT_IN_FMAL, "fmal", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
 DEF_C99_BUILTIN        (BUILT_IN_FMAX, "fmax", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_FMAXF, "fmaxf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_FMAXL, "fmaxl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_FMIN, "fmin", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
Index: gcc/testsuite/gcc.dg/tree-ssa/fegsetround.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/fegsetround.c	(revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/fegsetround.c	(working copy)
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -O -fdump-tree-optimized" } */
+
+#include <fenv.h>
+
+int a;
+int f ()
+{
+  a = 42;
+  // don't read a
+  int x = fegetround ();
+  fesetround (x + 1);
+  a = 0;
+  return a;
+}
+int g ()
+{
+  a = 0;
+  // don't write a
+  int x = fegetround ();
+  fesetround (x + 1);
+  return a;
+}
+int h ()
+{
+  // pure
+  return fegetround () - fegetround ();
+}
+
+/* { dg-final { scan-tree-dump-times "return 0" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-not "a = 42" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */

Property changes on: gcc/testsuite/gcc.dg/tree-ssa/fegsetround.c
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision URL
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: gcc/tree-ssa-alias.c
===================================================================
--- gcc/tree-ssa-alias.c	(revision 208045)
+++ gcc/tree-ssa-alias.c	(working copy)
@@ -1537,20 +1537,22 @@ ref_maybe_used_by_call_p_1 (gimple call,
 	case BUILT_IN_MODFF:
 	case BUILT_IN_MODFL:
 	case BUILT_IN_REMQUO:
 	case BUILT_IN_REMQUOF:
 	case BUILT_IN_REMQUOL:
 	case BUILT_IN_SINCOS:
 	case BUILT_IN_SINCOSF:
 	case BUILT_IN_SINCOSL:
 	case BUILT_IN_ASSUME_ALIGNED:
 	case BUILT_IN_VA_END:
+	case BUILT_IN_FEGETROUND:
+	case BUILT_IN_FESETROUND:
 	  return false;
 	/* __sync_* builtins and some OpenMP builtins act as threading
 	   barriers.  */
 #undef DEF_SYNC_BUILTIN
 #define DEF_SYNC_BUILTIN(ENUM, NAME, TYPE, ATTRS) case ENUM:
 #include "sync-builtins.def"
 #undef DEF_SYNC_BUILTIN
 	case BUILT_IN_GOMP_ATOMIC_START:
 	case BUILT_IN_GOMP_ATOMIC_END:
 	case BUILT_IN_GOMP_BARRIER:
@@ -1831,20 +1833,21 @@ call_may_clobber_ref_p_1 (gimple call, a
 	case BUILT_IN_STRNDUP:
 	  /* Unix98 specifies that errno is set on allocation failure.  */
 	  if (flag_errno_math
 	      && targetm.ref_may_alias_errno (ref))
 	    return true;
 	  return false;
 	case BUILT_IN_STACK_SAVE:
 	case BUILT_IN_ALLOCA:
 	case BUILT_IN_ALLOCA_WITH_ALIGN:
 	case BUILT_IN_ASSUME_ALIGNED:
+	case BUILT_IN_FESETROUND:
 	  return false;
 	/* But posix_memalign stores a pointer into the memory pointed to
 	   by its first argument.  */
 	case BUILT_IN_POSIX_MEMALIGN:
 	  {
 	    tree ptrptr = gimple_call_arg (call, 0);
 	    ao_ref dref;
 	    ao_ref_init_from_ptr_and_size (&dref, ptrptr,
 					   TYPE_SIZE_UNIT (ptr_type_node));
 	    return (refs_may_alias_p_1 (&dref, ref, false)


More information about the Gcc-patches mailing list