Commit e4fbead1 by Roger Sayle Committed by Roger Sayle

builtins.c (expand_builtin_signbit): Extend to handle floating point modes wider…

builtins.c (expand_builtin_signbit): Extend to handle floating point modes wider than the largest integer type...


	* builtins.c (expand_builtin_signbit): Extend to handle floating
	point modes wider than the largest integer type, using the
	operand_subword_force function to obtain the signbit's word.

	* gcc.dg/builtins-32.c: Add new run-time tests for long double.

From-SVN: r96263
parent 985f2d8f
2005-03-10 Roger Sayle <roger@eyesopen.com>
* builtins.c (expand_builtin_signbit): Extend to handle floating
point modes wider than the largest integer type, using the
operand_subword_force function to obtain the signbit's word.
2005-03-10 Jakub Jelinek <jakub@redhat.com> 2005-03-10 Jakub Jelinek <jakub@redhat.com>
PR target/20322 PR target/20322
......
...@@ -4957,7 +4957,7 @@ expand_builtin_signbit (tree exp, rtx target) ...@@ -4957,7 +4957,7 @@ expand_builtin_signbit (tree exp, rtx target)
enum machine_mode fmode, imode, rmode; enum machine_mode fmode, imode, rmode;
HOST_WIDE_INT hi, lo; HOST_WIDE_INT hi, lo;
tree arg, arglist; tree arg, arglist;
int bitpos; int word, bitpos;
rtx temp; rtx temp;
arglist = TREE_OPERAND (exp, 1); arglist = TREE_OPERAND (exp, 1);
...@@ -4971,7 +4971,8 @@ expand_builtin_signbit (tree exp, rtx target) ...@@ -4971,7 +4971,8 @@ expand_builtin_signbit (tree exp, rtx target)
/* For floating point formats without a sign bit, implement signbit /* For floating point formats without a sign bit, implement signbit
as "ARG < 0.0". */ as "ARG < 0.0". */
if (fmt->signbit < 0) bitpos = fmt->signbit;
if (bitpos < 0)
{ {
/* But we can't do this if the format supports signed zero. */ /* But we can't do this if the format supports signed zero. */
if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode)) if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
...@@ -4982,41 +4983,32 @@ expand_builtin_signbit (tree exp, rtx target) ...@@ -4982,41 +4983,32 @@ expand_builtin_signbit (tree exp, rtx target)
return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL); return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
} }
temp = expand_expr (arg, NULL_RTX, VOIDmode, 0);
if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
{
imode = int_mode_for_mode (fmode); imode = int_mode_for_mode (fmode);
if (imode == BLKmode) if (imode == BLKmode)
return 0; return 0;
temp = gen_lowpart (imode, temp);
bitpos = fmt->signbit; }
/* Handle targets with different FP word orders. */ else
if (FLOAT_WORDS_BIG_ENDIAN != WORDS_BIG_ENDIAN)
{ {
int nwords = GET_MODE_BITSIZE (fmode) / BITS_PER_WORD; imode = word_mode;
int word = nwords - (bitpos / BITS_PER_WORD) - 1; /* Handle targets with different FP word orders. */
bitpos = word * BITS_PER_WORD + bitpos % BITS_PER_WORD; if (FLOAT_WORDS_BIG_ENDIAN)
word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
else
word = bitpos / BITS_PER_WORD;
temp = operand_subword_force (temp, word, fmode);
bitpos = bitpos % BITS_PER_WORD;
} }
/* If the sign bit is not in the lowpart and the floating point format /* If the bitpos is within the "result mode" lowpart, the operation
is wider than an integer, check that is twice the size of an integer can be implement with a single bitwise AND. Otherwise, we need
so that we can use gen_highpart below. */ a right shift and an AND. */
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); if (bitpos < GET_MODE_BITSIZE (rmode))
temp = gen_lowpart (imode, temp);
if (GET_MODE_BITSIZE (imode) > GET_MODE_BITSIZE (rmode))
{
if (BYTES_BIG_ENDIAN)
bitpos = GET_MODE_BITSIZE (imode) - 1 - bitpos;
temp = copy_to_mode_reg (imode, temp);
temp = extract_bit_field (temp, 1, bitpos, 1,
NULL_RTX, rmode, rmode);
}
else
{ {
if (GET_MODE_BITSIZE (imode) < GET_MODE_BITSIZE (rmode))
temp = gen_lowpart (rmode, temp);
if (bitpos < HOST_BITS_PER_WIDE_INT) if (bitpos < HOST_BITS_PER_WIDE_INT)
{ {
hi = 0; hi = 0;
...@@ -5028,11 +5020,24 @@ expand_builtin_signbit (tree exp, rtx target) ...@@ -5028,11 +5020,24 @@ expand_builtin_signbit (tree exp, rtx target)
lo = 0; lo = 0;
} }
temp = force_reg (rmode, temp); if (imode != rmode)
temp = gen_lowpart (rmode, temp);
temp = expand_binop (rmode, and_optab, temp, temp = expand_binop (rmode, and_optab, temp,
immed_double_const (lo, hi, rmode), immed_double_const (lo, hi, rmode),
target, 1, OPTAB_LIB_WIDEN); NULL_RTX, 1, OPTAB_LIB_WIDEN);
}
else
{
/* Perform a logical right shift to place the signbit in the least
significant bit, then truncate the result to the desired mode
and mask just this bit. */
temp = expand_shift (RSHIFT_EXPR, imode, temp,
build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
temp = gen_lowpart (rmode, temp);
temp = expand_binop (rmode, and_optab, temp, const1_rtx,
NULL_RTX, 1, OPTAB_LIB_WIDEN);
} }
return temp; return temp;
} }
......
2005-03-10 Roger Sayle <roger@eyesopen.com>
* gcc.dg/builtins-32.c: Add new run-time tests for long double.
2005-03-10 Jakub Jelinek <jakub@redhat.com> 2005-03-10 Jakub Jelinek <jakub@redhat.com>
PR target/20322 PR target/20322
......
...@@ -12,6 +12,7 @@ extern void abort(void); ...@@ -12,6 +12,7 @@ extern void abort(void);
extern int signbit(double); extern int signbit(double);
extern int signbitf(float); extern int signbitf(float);
extern int signbitl(long double);
int test (double x) int test (double x)
{ {
...@@ -23,18 +24,35 @@ int testf (float x) ...@@ -23,18 +24,35 @@ int testf (float x)
return signbitf(x); return signbitf(x);
} }
int testl (long double x)
{
return signbitl(x);
}
int main() int main()
{ {
if (test (0.0) != 0)
abort ();
if (test (1.0) != 0) if (test (1.0) != 0)
abort (); abort ();
if (test (-2.0) == 0) if (test (-2.0) == 0)
abort (); abort ();
if (testf (0.0f) != 0)
abort ();
if (testf (1.0f) != 0) if (testf (1.0f) != 0)
abort (); abort ();
if (testf (-2.0f) == 0) if (testf (-2.0f) == 0)
abort (); abort ();
if (testl (0.0l) != 0)
abort ();
if (testl (1.0l) != 0)
abort ();
if (testl (-2.0l) == 0)
abort ();
return 0; 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