static tree fold_builtin_abs (location_t, tree, tree);
static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
enum tree_code);
+static tree fold_builtin_iseqsig (location_t, tree, tree);
static tree fold_builtin_varargs (location_t, tree, tree*, int);
static tree fold_builtin_strpbrk (location_t, tree, tree, tree, tree);
fold_build2_loc (loc, code, type, arg0, arg1));
}
+/* Fold a call to __builtin_iseqsig(). ARG0 and ARG1 are the arguments.
+ After choosing the wider floating-point type for the comparison,
+ the code is folded to:
+ SAVE_EXPR<ARG0> >= SAVE_EXPR<ARG1> && SAVE_EXPR<ARG0> <= SAVE_EXPR<ARG1> */
+
+static tree
+fold_builtin_iseqsig (location_t loc, tree arg0, tree arg1)
+{
+ tree type0, type1;
+ enum tree_code code0, code1;
+ tree cmp1, cmp2, cmp_type = NULL_TREE;
+
+ type0 = TREE_TYPE (arg0);
+ type1 = TREE_TYPE (arg1);
+
+ code0 = TREE_CODE (type0);
+ code1 = TREE_CODE (type1);
+
+ if (code0 == REAL_TYPE && code1 == REAL_TYPE)
+ /* Choose the wider of two real types. */
+ cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
+ ? type0 : type1;
+ else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
+ cmp_type = type0;
+ else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
+ cmp_type = type1;
+
+ arg0 = builtin_save_expr (fold_convert_loc (loc, cmp_type, arg0));
+ arg1 = builtin_save_expr (fold_convert_loc (loc, cmp_type, arg1));
+
+ cmp1 = fold_build2_loc (loc, GE_EXPR, integer_type_node, arg0, arg1);
+ cmp2 = fold_build2_loc (loc, LE_EXPR, integer_type_node, arg0, arg1);
+
+ return fold_build2_loc (loc, TRUTH_AND_EXPR, integer_type_node, cmp1, cmp2);
+}
+
/* Fold __builtin_{,s,u}{add,sub,mul}{,l,ll}_overflow, either into normal
arithmetics if it can never overflow, or into internal functions that
return both result of arithmetics and overflowed boolean flag in
arg0, arg1, UNORDERED_EXPR,
NOP_EXPR);
+ case BUILT_IN_ISEQSIG:
+ return fold_builtin_iseqsig (loc, arg0, arg1);
+
/* We do the folding for va_start in the expander. */
case BUILT_IN_VA_START:
break;
case BUILT_IN_ISLESSEQUAL:
case BUILT_IN_ISLESSGREATER:
case BUILT_IN_ISUNORDERED:
+ case BUILT_IN_ISEQSIG:
case BUILT_IN_VA_ARG_PACK:
case BUILT_IN_VA_ARG_PACK_LEN:
case BUILT_IN_VA_COPY:
DEF_GCC_BUILTIN (BUILT_IN_ISLESSEQUAL, "islessequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
DEF_GCC_BUILTIN (BUILT_IN_ISLESSGREATER, "islessgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
DEF_GCC_BUILTIN (BUILT_IN_ISUNORDERED, "isunordered", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_ISEQSIG, "iseqsig", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
DEF_GCC_BUILTIN (BUILT_IN_ISSIGNALING, "issignaling", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_LABS, "labs", BT_FN_LONG_LONG, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_BUILTIN (BUILT_IN_LLABS, "llabs", BT_FN_LONGLONG_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
case BUILT_IN_ISLESSEQUAL:
case BUILT_IN_ISLESSGREATER:
case BUILT_IN_ISUNORDERED:
+ case BUILT_IN_ISEQSIG:
if (builtin_function_validate_nargs (loc, fndecl, nargs, 2))
{
enum tree_code code0, code1;
@node Other Builtins
@section Other Built-in Functions Provided by GCC
@cindex built-in functions
+@findex __builtin_iseqsig
@findex __builtin_isfinite
@findex __builtin_isnormal
@findex __builtin_isgreater
@code{islessgreater}, and @code{isunordered}) , with @code{__builtin_}
prefixed. We intend for a library implementor to be able to simply
@code{#define} each standard macro to its built-in equivalent.
-In the same fashion, GCC provides @code{fpclassify}, @code{isfinite},
-@code{isinf_sign}, @code{isnormal} and @code{signbit} built-ins used with
-@code{__builtin_} prefixed. The @code{isinf} and @code{isnan}
+In the same fashion, GCC provides @code{fpclassify}, @code{iseqsig},
+@code{isfinite}, @code{isinf_sign}, @code{isnormal} and @code{signbit} built-ins
+used with @code{__builtin_} prefixed. The @code{isinf} and @code{isnan}
built-in functions appear both with and without the @code{__builtin_} prefix.
With @code{-ffinite-math-only} option the @code{isinf} and @code{isnan}
built-in functions will always return 0.
--- /dev/null
+/* { dg-do run { xfail powerpc*-*-* } } */
+/* remove the xfail for powerpc when pr58684 is fixed */
+/* { dg-add-options ieee } */
+/* { dg-additional-options "-fsignaling-nans" } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+void
+ftrue (float x, float y)
+{
+ if (!__builtin_iseqsig (x, y))
+ __builtin_abort ();
+}
+
+void
+ffalse (float x, float y)
+{
+ if (__builtin_iseqsig (x, y))
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ volatile float f1, f2;
+
+ f1 = 0.f; f2 = 0.f;
+ ftrue (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 0.f; f2 = -0.f;
+ ftrue (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 0.f; f2 = 1.f;
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = -0.f; f2 = 1.f;
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 0.f; f2 = __builtin_inff();
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = -0.f; f2 = __builtin_inff();
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 0.f; f2 = __builtin_nanf("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = -0.f; f2 = __builtin_nanf("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = 1.f; f2 = 1.f;
+ ftrue (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 1.f; f2 = 0.f;
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 1.f; f2 = -0.f;
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 1.f; f2 = __builtin_inff();
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 1.f; f2 = __builtin_nanf("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = __builtin_inff(); f2 = __builtin_inff();
+ ftrue (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = __builtin_inff(); f2 = __builtin_nanf("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = __builtin_nanf(""); f2 = __builtin_nanf("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = __builtin_nansf(""); f2 = 1.f;
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = 1.f; f2 = __builtin_nansf("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = __builtin_nansf(""); f2 = __builtin_nansf("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ return 0;
+}
--- /dev/null
+/* { dg-do run { xfail powerpc*-*-* } } */
+/* remove the xfail for powerpc when pr58684 is fixed */
+/* { dg-add-options ieee } */
+/* { dg-additional-options "-fsignaling-nans" } */
+/* { dg-require-effective-target fenv_exceptions_double } */
+
+#include <fenv.h>
+
+void
+ftrue (double x, double y)
+{
+ if (!__builtin_iseqsig (x, y))
+ __builtin_abort ();
+}
+
+void
+ffalse (double x, double y)
+{
+ if (__builtin_iseqsig (x, y))
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ volatile double f1, f2;
+
+ f1 = 0.; f2 = 0.;
+ ftrue (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 0.; f2 = -0.;
+ ftrue (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 0.; f2 = 1.;
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = -0.; f2 = 1.;
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 0.; f2 = __builtin_inf();
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = -0.; f2 = __builtin_inf();
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 0.; f2 = __builtin_nan("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = -0.; f2 = __builtin_nan("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = 1.; f2 = 1.;
+ ftrue (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 1.; f2 = 0.;
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 1.; f2 = -0.;
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 1.; f2 = __builtin_inf();
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 1.; f2 = __builtin_nan("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = __builtin_inf(); f2 = __builtin_inf();
+ ftrue (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = __builtin_inf(); f2 = __builtin_nan("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = __builtin_nan(""); f2 = __builtin_nan("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = __builtin_nans(""); f2 = 1.;
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = 1.; f2 = __builtin_nans("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = __builtin_nans(""); f2 = __builtin_nans("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ return 0;
+}
--- /dev/null
+/* { dg-do run { xfail powerpc*-*-* } } */
+/* remove the xfail for powerpc when pr58684 is fixed */
+/* { dg-add-options ieee } */
+/* { dg-additional-options "-fsignaling-nans" } */
+/* { dg-require-effective-target fenv_exceptions_long_double } */
+
+#include <fenv.h>
+
+void
+ftrue (long double x, long double y)
+{
+ if (!__builtin_iseqsig (x, y))
+ __builtin_abort ();
+}
+
+void
+ffalse (long double x, long double y)
+{
+ if (__builtin_iseqsig (x, y))
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ volatile long double f1, f2;
+
+ f1 = 0.L; f2 = 0.f;
+ ftrue (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 0.L; f2 = -0.f;
+ ftrue (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 0.L; f2 = 1.f;
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = -0.L; f2 = 1.f;
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 0.L; f2 = __builtin_infl();
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = -0.L; f2 = __builtin_infl();
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 0.L; f2 = __builtin_nanl("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = -0.L; f2 = __builtin_nanl("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = 1.L; f2 = 1.f;
+ ftrue (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 1.L; f2 = 0.f;
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 1.L; f2 = -0.f;
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 1.L; f2 = __builtin_infl();
+ ffalse (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = 1.L; f2 = __builtin_nanl("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = __builtin_infl(); f2 = __builtin_infl();
+ ftrue (f1, f2);
+ if (fetestexcept (FE_INVALID)) __builtin_abort ();
+
+ f1 = __builtin_infl(); f2 = __builtin_nanl("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = __builtin_nanl(""); f2 = __builtin_nanl("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = __builtin_nansl(""); f2 = 1.L;
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = 1.L; f2 = __builtin_nansl("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ f1 = __builtin_nansl(""); f2 = __builtin_nansl("");
+ ffalse (f1, f2);
+ if (!fetestexcept (FE_INVALID)) __builtin_abort ();
+ feclearexcept (FE_INVALID);
+
+ return 0;
+}