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);
} }
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 = expand_expr (arg, NULL_RTX, VOIDmode, 0);
temp = gen_lowpart (imode, temp); if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
if (GET_MODE_BITSIZE (imode) > GET_MODE_BITSIZE (rmode))
{ {
if (BYTES_BIG_ENDIAN) imode = int_mode_for_mode (fmode);
bitpos = GET_MODE_BITSIZE (imode) - 1 - bitpos; if (imode == BLKmode)
temp = copy_to_mode_reg (imode, temp); return 0;
temp = extract_bit_field (temp, 1, bitpos, 1, temp = gen_lowpart (imode, temp);
NULL_RTX, rmode, rmode);
} }
else else
{ {
if (GET_MODE_BITSIZE (imode) < GET_MODE_BITSIZE (rmode)) imode = word_mode;
temp = gen_lowpart (rmode, temp); /* Handle targets with different FP word orders. */
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 bitpos is within the "result mode" lowpart, the operation
can be implement with a single bitwise AND. Otherwise, we need
a right shift and an AND. */
if (bitpos < GET_MODE_BITSIZE (rmode))
{
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