diff options
author | Roger Sayle <roger@eyesopen.com> | 2004-02-01 14:59:15 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2004-02-01 14:59:15 +0000 |
commit | ef79730c93540ee721d5403b276ec3d11a7c0123 (patch) | |
tree | 5685a3fc60b869436c4a4d9ec1766345aa482fd1 /gcc | |
parent | a80cdb0f54b9c0d290d45485ae23e9cc13d5039e (diff) | |
download | gcc-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/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/builtins.c | 144 | ||||
-rw-r--r-- | gcc/builtins.def | 3 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-1.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-31.c | 36 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-32.c | 40 |
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; +} + |