Commit ef79730c by Roger Sayle Committed by Roger Sayle

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
parent a80cdb0f
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> 2004-02-01 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.md (adddi3_internal_2): Remove superfluous %s. * config/mips/mips.md (adddi3_internal_2): Remove superfluous %s.
......
...@@ -152,6 +152,7 @@ static tree fold_trunc_transparent_mathfn (tree); ...@@ -152,6 +152,7 @@ static tree fold_trunc_transparent_mathfn (tree);
static bool readonly_data_expr (tree); static bool readonly_data_expr (tree);
static rtx expand_builtin_fabs (tree, rtx, rtx); static rtx expand_builtin_fabs (tree, rtx, rtx);
static rtx expand_builtin_cabs (tree, 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_cabs (tree, tree, tree);
static tree fold_builtin_trunc (tree); static tree fold_builtin_trunc (tree);
static tree fold_builtin_floor (tree); static tree fold_builtin_floor (tree);
...@@ -166,6 +167,7 @@ static tree fold_builtin_strncpy (tree); ...@@ -166,6 +167,7 @@ static tree fold_builtin_strncpy (tree);
static tree fold_builtin_memcmp (tree); static tree fold_builtin_memcmp (tree);
static tree fold_builtin_strcmp (tree); static tree fold_builtin_strcmp (tree);
static tree fold_builtin_strncmp (tree); static tree fold_builtin_strncmp (tree);
static tree fold_builtin_signbit (tree);
/* Return the alignment in bits of EXP, a pointer valued expression. /* Return the alignment in bits of EXP, a pointer valued expression.
But don't return more than MAX_ALIGN no matter what. 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) ...@@ -4920,6 +4922,97 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
return 0; 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, /* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient 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, ...@@ -5411,6 +5504,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
return target; return target;
break; 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. */ /* Various hooks for the DWARF 2 __throw routine. */
case BUILT_IN_UNWIND_INIT: case BUILT_IN_UNWIND_INIT:
expand_builtin_unwind_init (); expand_builtin_unwind_init ();
...@@ -6528,6 +6629,44 @@ fold_builtin_strncmp (tree exp) ...@@ -6528,6 +6629,44 @@ fold_builtin_strncmp (tree exp)
return 0; 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 /* Used by constant folding to eliminate some builtin calls early. EXP is
the CALL_EXPR of a call to a builtin function. */ the CALL_EXPR of a call to a builtin function. */
...@@ -6949,6 +7088,11 @@ fold_builtin (tree exp) ...@@ -6949,6 +7088,11 @@ fold_builtin (tree exp)
case BUILT_IN_STRNCMP: case BUILT_IN_STRNCMP:
return fold_builtin_strncmp (exp); return fold_builtin_strncmp (exp);
case BUILT_IN_SIGNBIT:
case BUILT_IN_SIGNBITF:
case BUILT_IN_SIGNBITL:
return fold_builtin_signbit (exp);
default: default:
break; break;
} }
......
...@@ -321,6 +321,9 @@ DEF_C99_BUILTIN (BUILT_IN_SCALBLNL, "scalblnl", BT_FN_LONGDOUBLE_LONGDOUB ...@@ -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_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_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_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_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_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) DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNIFICANDL, "significandl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
......
...@@ -4988,6 +4988,9 @@ v4si f (v4si a, v4si b, v4si c) ...@@ -4988,6 +4988,9 @@ v4si f (v4si a, v4si b, v4si c)
@findex scalbn @findex scalbn
@findex scalbnf @findex scalbnf
@findex scanfnl @findex scanfnl
@findex signbit
@findex signbitf
@findex signbitl
@findex significand @findex significand
@findex significandf @findex significandf
@findex significandl @findex significandl
...@@ -5082,6 +5085,7 @@ Outside strict ISO C mode (@option{-ansi}, @option{-std=c89} or ...@@ -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{j1}, @code{jnf}, @code{jnl}, @code{jn}, @code{mempcpy},
@code{pow10f}, @code{pow10l}, @code{pow10}, @code{printf_unlocked}, @code{pow10f}, @code{pow10l}, @code{pow10}, @code{printf_unlocked},
@code{rindex}, @code{scalbf}, @code{scalbl}, @code{scalb}, @code{rindex}, @code{scalbf}, @code{scalbl}, @code{scalb},
@code{signbit}, @code{signbitf}, @code{signbitl},
@code{significandf}, @code{significandl}, @code{significand}, @code{significandf}, @code{significandl}, @code{significand},
@code{sincosf}, @code{sincosl}, @code{sincos}, @code{stpcpy}, @code{sincosf}, @code{sincosl}, @code{sincos}, @code{stpcpy},
@code{strdup}, @code{strfmon}, @code{y0f}, @code{y0l}, @code{y0}, @code{strdup}, @code{strfmon}, @code{y0f}, @code{y0l}, @code{y0},
......
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> 2004-01-30 Andrew Pinski <pinskia@physics.uc.edu>
* objc.dg/call-super-2.m: Update line numbers * objc.dg/call-super-2.m: Update line numbers
......
...@@ -165,6 +165,7 @@ FPTEST1 (round) ...@@ -165,6 +165,7 @@ FPTEST1 (round)
FPTEST2 (scalb) FPTEST2 (scalb)
FPTEST2ARG2 (scalbln, int) FPTEST2ARG2 (scalbln, int)
FPTEST2ARG2 (scalbn, int) FPTEST2ARG2 (scalbn, int)
FPTEST1RET (signbit, int)
FPTEST1 (significand) FPTEST1 (significand)
FPTEST1 (sin) FPTEST1 (sin)
FPTEST3FPP23VOID (sincos) FPTEST3FPP23VOID (sincos)
......
/* 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;
}
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment