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:
parent
a80cdb0f54
commit
ef79730c93
@ -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.
|
||||
|
144
gcc/builtins.c
144
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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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},
|
||||
|
@ -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
|
||||
|
@ -165,6 +165,7 @@ FPTEST1 (round)
|
||||
FPTEST2 (scalb)
|
||||
FPTEST2ARG2 (scalbln, int)
|
||||
FPTEST2ARG2 (scalbn, int)
|
||||
FPTEST1RET (signbit, int)
|
||||
FPTEST1 (significand)
|
||||
FPTEST1 (sin)
|
||||
FPTEST3FPP23VOID (sincos)
|
||||
|
36
gcc/testsuite/gcc.dg/builtins-31.c
Normal file
36
gcc/testsuite/gcc.dg/builtins-31.c
Normal 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;
|
||||
}
|
||||
|
40
gcc/testsuite/gcc.dg/builtins-32.c
Normal file
40
gcc/testsuite/gcc.dg/builtins-32.c
Normal 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user