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
This commit is contained in:
Roger Sayle 2004-02-01 14:59:15 +00:00 committed by Roger Sayle
parent a80cdb0f54
commit ef79730c93
8 changed files with 247 additions and 0 deletions

View File

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

View File

@ -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;
}

View File

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

View File

@ -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},

View File

@ -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

View File

@ -165,6 +165,7 @@ FPTEST1 (round)
FPTEST2 (scalb)
FPTEST2ARG2 (scalbln, int)
FPTEST2ARG2 (scalbn, int)
FPTEST1RET (signbit, int)
FPTEST1 (significand)
FPTEST1 (sin)
FPTEST3FPP23VOID (sincos)

View File

@ -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;
}

View File

@ -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;
}