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.gli...@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
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)