aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2004-02-01 14:59:15 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2004-02-01 14:59:15 +0000
commitef79730c93540ee721d5403b276ec3d11a7c0123 (patch)
tree5685a3fc60b869436c4a4d9ec1766345aa482fd1 /gcc
parenta80cdb0f54b9c0d290d45485ae23e9cc13d5039e (diff)
downloadgcc-ef79730c93540ee721d5403b276ec3d11a7c0123.zip
gcc-ef79730c93540ee721d5403b276ec3d11a7c0123.tar.gz
gcc-ef79730c93540ee721d5403b276ec3d11a7c0123.tar.bz2
builtins.def (BUILT_IN_SIGNBIT, [...]): New GCC builtins.
* builtins.def (BUILT_IN_SIGNBIT, BUILT_IN_SIGNBITF, BUILT_IN_SIGNBITL): New GCC builtins. * builtins.c (expand_builtin_signbit): New function to RTL expand calls to signbit, signbitf and signbitl as inline intrinsics. (expand_builtin): Call expand_builtin_signbit for BUILT_IN_SIGNBIT*. (fold_builtin_signbit): New function to perform constant folding of signbit, signbitf and signbitl. (fold_builtin): Call fold_builtin_signbit for BUILT_IN_SIGNBIT*. * doc/extend.texi: Document new signbit{,f,l} builtins. * gcc.dg/builtins-1.c: Also test for __builtin_signbit{,f,l}. * gcc.dg/builtins-31.c: New testcase. * gcc.dg/builtins-32.c: New testcase. From-SVN: r77070
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/builtins.c144
-rw-r--r--gcc/builtins.def3
-rw-r--r--gcc/doc/extend.texi4
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/builtins-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/builtins-31.c36
-rw-r--r--gcc/testsuite/gcc.dg/builtins-32.c40
8 files changed, 247 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 989f9e4..64e15f3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2004-02-01 Roger Sayle <roger@eyesopen.com>
+
+ * builtins.def (BUILT_IN_SIGNBIT, BUILT_IN_SIGNBITF,
+ BUILT_IN_SIGNBITL): New GCC builtins.
+ * builtins.c (expand_builtin_signbit): New function to RTL expand
+ calls to signbit, signbitf and signbitl as inline intrinsics.
+ (expand_builtin): Call expand_builtin_signbit for BUILT_IN_SIGNBIT*.
+ (fold_builtin_signbit): New function to perform constant folding
+ of signbit, signbitf and signbitl.
+ (fold_builtin): Call fold_builtin_signbit for BUILT_IN_SIGNBIT*.
+
+ * doc/extend.texi: Document new signbit{,f,l} builtins.
+
2004-02-01 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.md (adddi3_internal_2): Remove superfluous %s.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 2dfc0e8..8b15e7c 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -152,6 +152,7 @@ static tree fold_trunc_transparent_mathfn (tree);
static bool readonly_data_expr (tree);
static rtx expand_builtin_fabs (tree, rtx, rtx);
static rtx expand_builtin_cabs (tree, rtx);
+static rtx expand_builtin_signbit (tree, rtx);
static tree fold_builtin_cabs (tree, tree, tree);
static tree fold_builtin_trunc (tree);
static tree fold_builtin_floor (tree);
@@ -166,6 +167,7 @@ static tree fold_builtin_strncpy (tree);
static tree fold_builtin_memcmp (tree);
static tree fold_builtin_strcmp (tree);
static tree fold_builtin_strncmp (tree);
+static tree fold_builtin_signbit (tree);
/* Return the alignment in bits of EXP, a pointer valued expression.
But don't return more than MAX_ALIGN no matter what.
@@ -4920,6 +4922,97 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
return 0;
}
+
+/* Expand a call to the built-in signbit, signbitf or signbitl function.
+ Return NULL_RTX if a normal call should be emitted rather than expanding
+ the function in-line. EXP is the expression that is a call to the builtin
+ function; if convenient, the result should be placed in TARGET. */
+
+static rtx
+expand_builtin_signbit (tree exp, rtx target)
+{
+ const struct real_format *fmt;
+ enum machine_mode fmode, imode, rmode;
+ HOST_WIDE_INT hi, lo;
+ tree arg, arglist;
+ int bitpos;
+ rtx temp;
+
+ arglist = TREE_OPERAND (exp, 1);
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return 0;
+
+ arg = TREE_VALUE (arglist);
+ fmode = TYPE_MODE (TREE_TYPE (arg));
+ rmode = TYPE_MODE (TREE_TYPE (exp));
+ fmt = REAL_MODE_FORMAT (fmode);
+
+ /* For floating point formats without a sign bit, implement signbit
+ as "ARG < 0.0". */
+ if (fmt->signbit < 0)
+ {
+ /* But we can't do this if the format supports signed zero. */
+ if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
+ return 0;
+
+ arg = fold (build (LT_EXPR, TREE_TYPE (exp), arg,
+ build_real (TREE_TYPE (arg), dconst0)));
+ return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
+ }
+
+ imode = int_mode_for_mode (fmode);
+ if (imode == BLKmode)
+ return 0;
+
+ bitpos = fmt->signbit;
+ /* Handle targets with different FP word orders. */
+ if (FLOAT_WORDS_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+ {
+ int nwords = GET_MODE_BITSIZE (fmode) / BITS_PER_WORD;
+ int word = nwords - (bitpos / BITS_PER_WORD) - 1;
+ bitpos = word * BITS_PER_WORD + bitpos % BITS_PER_WORD;
+ }
+
+ /* If the sign bit is not in the lowpart and the floating point format
+ is wider than an integer, check that is twice the size of an integer
+ so that we can use gen_highpart below. */
+ if (bitpos >= GET_MODE_BITSIZE (rmode)
+ && GET_MODE_BITSIZE (imode) != 2 * GET_MODE_BITSIZE (rmode))
+ return 0;
+
+ temp = expand_expr (arg, NULL_RTX, VOIDmode, 0);
+ temp = gen_lowpart (imode, temp);
+
+ if (GET_MODE_BITSIZE (imode) < GET_MODE_BITSIZE (rmode))
+ temp = gen_lowpart (rmode, temp);
+ else if (GET_MODE_BITSIZE (imode) > GET_MODE_BITSIZE (rmode))
+ {
+ if (bitpos > GET_MODE_BITSIZE (rmode))
+ {
+ temp = gen_highpart (rmode, temp);
+ bitpos %= GET_MODE_BITSIZE (rmode);
+ }
+ else
+ temp = gen_lowpart (rmode, temp);
+ }
+
+ if (bitpos < HOST_BITS_PER_WIDE_INT)
+ {
+ hi = 0;
+ lo = (HOST_WIDE_INT) 1 << bitpos;
+ }
+ else
+ {
+ hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
+ lo = 0;
+ }
+
+ temp = force_reg (rmode, temp);
+ temp = expand_binop (rmode, and_optab, temp,
+ immed_double_const (lo, hi, rmode),
+ target, 1, OPTAB_LIB_WIDEN);
+ return temp;
+}
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient
@@ -5411,6 +5504,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
return target;
break;
+ case BUILT_IN_SIGNBIT:
+ case BUILT_IN_SIGNBITF:
+ case BUILT_IN_SIGNBITL:
+ target = expand_builtin_signbit (exp, target);
+ if (target)
+ return target;
+ break;
+
/* Various hooks for the DWARF 2 __throw routine. */
case BUILT_IN_UNWIND_INIT:
expand_builtin_unwind_init ();
@@ -6528,6 +6629,44 @@ fold_builtin_strncmp (tree exp)
return 0;
}
+/* Fold function call to builtin signbit, signbitf or signbitl. Return
+ NULL_TREE if no simplification can be made. */
+
+static tree
+fold_builtin_signbit (tree exp)
+{
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree arg, temp;
+
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return NULL_TREE;
+
+ arg = TREE_VALUE (arglist);
+
+ /* If ARG is a compile-time constant, determine the result. */
+ if (TREE_CODE (arg) == REAL_CST
+ && !TREE_CONSTANT_OVERFLOW (arg))
+ {
+ REAL_VALUE_TYPE c;
+
+ c = TREE_REAL_CST (arg);
+ temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
+ return convert (TREE_TYPE (exp), temp);
+ }
+
+ /* If ARG is non-negative, the result is always zero. */
+ if (tree_expr_nonnegative_p (arg))
+ return omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg);
+
+ /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
+ if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
+ return fold (build (LT_EXPR, TREE_TYPE (exp), arg,
+ build_real (TREE_TYPE (arg), dconst0)));
+
+ return NULL_TREE;
+}
+
+
/* Used by constant folding to eliminate some builtin calls early. EXP is
the CALL_EXPR of a call to a builtin function. */
@@ -6949,6 +7088,11 @@ fold_builtin (tree exp)
case BUILT_IN_STRNCMP:
return fold_builtin_strncmp (exp);
+ case BUILT_IN_SIGNBIT:
+ case BUILT_IN_SIGNBITF:
+ case BUILT_IN_SIGNBITL:
+ return fold_builtin_signbit (exp);
+
default:
break;
}
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 27cb2b6..a813580 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -321,6 +321,9 @@ DEF_C99_BUILTIN (BUILT_IN_SCALBLNL, "scalblnl", BT_FN_LONGDOUBLE_LONGDOUB
DEF_C99_BUILTIN (BUILT_IN_SCALBN, "scalbn", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_SCALBNF, "scalbnf", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_SCALBNL, "scalbnl", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBIT, "signbit", BT_FN_INT_DOUBLE, ATTR_CONST_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBITF, "signbitf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBITL, "signbitl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNIFICAND, "significand", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNIFICANDF, "significandf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNIFICANDL, "significandl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index e2bfd93..9f0f6b9 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -4988,6 +4988,9 @@ v4si f (v4si a, v4si b, v4si c)
@findex scalbn
@findex scalbnf
@findex scanfnl
+@findex signbit
+@findex signbitf
+@findex signbitl
@findex significand
@findex significandf
@findex significandl
@@ -5082,6 +5085,7 @@ Outside strict ISO C mode (@option{-ansi}, @option{-std=c89} or
@code{j1}, @code{jnf}, @code{jnl}, @code{jn}, @code{mempcpy},
@code{pow10f}, @code{pow10l}, @code{pow10}, @code{printf_unlocked},
@code{rindex}, @code{scalbf}, @code{scalbl}, @code{scalb},
+@code{signbit}, @code{signbitf}, @code{signbitl},
@code{significandf}, @code{significandl}, @code{significand},
@code{sincosf}, @code{sincosl}, @code{sincos}, @code{stpcpy},
@code{strdup}, @code{strfmon}, @code{y0f}, @code{y0l}, @code{y0},
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 18aa48b..afd9ce6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2004-02-01 Roger Sayle <roger@eyesopen.com>
+
+ * gcc.dg/builtins-1.c: Also test for __builtin_signbit{,f,l}.
+ * gcc.dg/builtins-31.c: New testcase.
+ * gcc.dg/builtins-32.c: New testcase.
+
2004-01-30 Andrew Pinski <pinskia@physics.uc.edu>
* objc.dg/call-super-2.m: Update line numbers
diff --git a/gcc/testsuite/gcc.dg/builtins-1.c b/gcc/testsuite/gcc.dg/builtins-1.c
index 41bd8d5..18c45d1 100644
--- a/gcc/testsuite/gcc.dg/builtins-1.c
+++ b/gcc/testsuite/gcc.dg/builtins-1.c
@@ -165,6 +165,7 @@ FPTEST1 (round)
FPTEST2 (scalb)
FPTEST2ARG2 (scalbln, int)
FPTEST2ARG2 (scalbn, int)
+FPTEST1RET (signbit, int)
FPTEST1 (significand)
FPTEST1 (sin)
FPTEST3FPP23VOID (sincos)
diff --git a/gcc/testsuite/gcc.dg/builtins-31.c b/gcc/testsuite/gcc.dg/builtins-31.c
new file mode 100644
index 0000000..6e1bda0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtins-31.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2004 Free Software Foundation.
+
+ Check that constant folding of signbit, signbitf and signbitl math
+ functions doesn't break anything and produces the expected results.
+
+ Written by Roger Sayle, 28th January 2004. */
+
+/* { dg-do link } */
+/* { dg-options "-O2" } */
+
+extern void link_error(void);
+
+extern int signbit(double);
+extern int signbitf(float);
+extern int signbitl(long double);
+
+int main()
+{
+ if (signbit (1.0) != 0)
+ link_error ();
+ if (signbit (-2.0) == 0)
+ link_error ();
+
+ if (signbitf (1.0f) != 0)
+ link_error ();
+ if (signbitf (-2.0f) == 0)
+ link_error ();
+
+ if (signbitl (1.0l) != 0)
+ link_error ();
+ if (signbitl (-2.0f) == 0)
+ link_error ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/builtins-32.c b/gcc/testsuite/gcc.dg/builtins-32.c
new file mode 100644
index 0000000..3a35dc6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtins-32.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 2004 Free Software Foundation.
+
+ Check that constant folding of signbit, signbitf and signbitl math
+ functions doesn't break anything and produces the expected results.
+
+ Written by Roger Sayle, 28th January 2004. */
+
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort(void);
+
+extern int signbit(double);
+extern int signbitf(float);
+
+int test (double x)
+{
+ return signbit(x);
+}
+
+int testf (float x)
+{
+ return signbitf(x);
+}
+
+int main()
+{
+ if (test (1.0) != 0)
+ abort ();
+ if (test (-2.0) == 0)
+ abort ();
+
+ if (testf (1.0f) != 0)
+ abort ();
+ if (testf (-2.0f) == 0)
+ abort ();
+
+ return 0;
+}
+