i386.c (ix86_expand_rint): Fix issues with signed zeros.
2006-11-01 Richard Guenther <rguenther@suse.de> * config/i386/i386.c (ix86_expand_rint): Fix issues with signed zeros. (ix86_expand_floorceildf_32): Likewise. (ix86_expand_floorceil): Likewise. (ix86_expand_trunc): Likewise. * testsuite/gcc.target/i386/fpprec-1.c: New testcase. From-SVN: r118373
This commit is contained in:
parent
4a574196f5
commit
7e35fcb30e
|
@ -1,3 +1,11 @@
|
||||||
|
2006-11-01 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
|
* config/i386/i386.c (ix86_expand_rint): Fix issues with
|
||||||
|
signed zeros.
|
||||||
|
(ix86_expand_floorceildf_32): Likewise.
|
||||||
|
(ix86_expand_floorceil): Likewise.
|
||||||
|
(ix86_expand_trunc): Likewise.
|
||||||
|
|
||||||
2006-10-31 Andrew Pinski <pinskia@gmail.com>
|
2006-10-31 Andrew Pinski <pinskia@gmail.com>
|
||||||
|
|
||||||
* doc/invoke.texi (-fkeep-inline-functions): Change "GNU C"
|
* doc/invoke.texi (-fkeep-inline-functions): Change "GNU C"
|
||||||
|
|
|
@ -19423,10 +19423,11 @@ void
|
||||||
ix86_expand_rint (rtx operand0, rtx operand1)
|
ix86_expand_rint (rtx operand0, rtx operand1)
|
||||||
{
|
{
|
||||||
/* C code for the stuff we're doing below:
|
/* C code for the stuff we're doing below:
|
||||||
if (!isless (fabs (operand1), 2**52))
|
xa = fabs (operand1);
|
||||||
|
if (!isless (xa, 2**52))
|
||||||
return operand1;
|
return operand1;
|
||||||
tmp = copysign (2**52, operand1);
|
xa = xa + 2**52 - 2**52;
|
||||||
return operand1 + tmp - tmp;
|
return copysign (xa, operand1);
|
||||||
*/
|
*/
|
||||||
enum machine_mode mode = GET_MODE (operand0);
|
enum machine_mode mode = GET_MODE (operand0);
|
||||||
rtx res, xa, label, TWO52, mask;
|
rtx res, xa, label, TWO52, mask;
|
||||||
|
@ -19441,10 +19442,10 @@ ix86_expand_rint (rtx operand0, rtx operand1)
|
||||||
TWO52 = ix86_gen_TWO52 (mode);
|
TWO52 = ix86_gen_TWO52 (mode);
|
||||||
label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
|
label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
|
||||||
|
|
||||||
ix86_sse_copysign_to_positive (TWO52, TWO52, res, mask);
|
expand_simple_binop (mode, PLUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
|
||||||
|
expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
|
||||||
|
|
||||||
expand_simple_binop (mode, PLUS, res, TWO52, res, 0, OPTAB_DIRECT);
|
ix86_sse_copysign_to_positive (res, xa, res, mask);
|
||||||
expand_simple_binop (mode, MINUS, res, TWO52, res, 0, OPTAB_DIRECT);
|
|
||||||
|
|
||||||
emit_label (label);
|
emit_label (label);
|
||||||
LABEL_NUSES (label) = 1;
|
LABEL_NUSES (label) = 1;
|
||||||
|
@ -19468,7 +19469,7 @@ ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
|
||||||
x2 -= 1;
|
x2 -= 1;
|
||||||
Compensate. Ceil:
|
Compensate. Ceil:
|
||||||
if (x2 < x)
|
if (x2 < x)
|
||||||
x2 += 1;
|
x2 -= -1;
|
||||||
return x2;
|
return x2;
|
||||||
*/
|
*/
|
||||||
enum machine_mode mode = GET_MODE (operand0);
|
enum machine_mode mode = GET_MODE (operand0);
|
||||||
|
@ -19494,14 +19495,17 @@ ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
|
||||||
/* xa = copysign (xa, operand1) */
|
/* xa = copysign (xa, operand1) */
|
||||||
ix86_sse_copysign_to_positive (xa, xa, res, mask);
|
ix86_sse_copysign_to_positive (xa, xa, res, mask);
|
||||||
|
|
||||||
/* generate 1.0 */
|
/* generate 1.0 or -1.0 */
|
||||||
one = force_reg (mode, const_double_from_real_value (dconst1, mode));
|
one = force_reg (mode,
|
||||||
|
const_double_from_real_value (do_floor
|
||||||
|
? dconst1 : dconstm1, mode));
|
||||||
|
|
||||||
/* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
|
/* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
|
||||||
tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
|
tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
|
||||||
emit_insn (gen_rtx_SET (VOIDmode, tmp,
|
emit_insn (gen_rtx_SET (VOIDmode, tmp,
|
||||||
gen_rtx_AND (mode, one, tmp)));
|
gen_rtx_AND (mode, one, tmp)));
|
||||||
expand_simple_binop (mode, do_floor ? MINUS : PLUS,
|
/* We always need to subtract here to preserve signed zero. */
|
||||||
|
expand_simple_binop (mode, MINUS,
|
||||||
xa, tmp, res, 0, OPTAB_DIRECT);
|
xa, tmp, res, 0, OPTAB_DIRECT);
|
||||||
|
|
||||||
emit_label (label);
|
emit_label (label);
|
||||||
|
@ -19526,10 +19530,12 @@ ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
|
||||||
Compensate. Ceil:
|
Compensate. Ceil:
|
||||||
if (x2 < x)
|
if (x2 < x)
|
||||||
x2 += 1;
|
x2 += 1;
|
||||||
|
if (HONOR_SIGNED_ZEROS (mode))
|
||||||
|
return copysign (x2, x);
|
||||||
return x2;
|
return x2;
|
||||||
*/
|
*/
|
||||||
enum machine_mode mode = GET_MODE (operand0);
|
enum machine_mode mode = GET_MODE (operand0);
|
||||||
rtx xa, xi, TWO52, tmp, label, one, res;
|
rtx xa, xi, TWO52, tmp, label, one, res, mask;
|
||||||
|
|
||||||
TWO52 = ix86_gen_TWO52 (mode);
|
TWO52 = ix86_gen_TWO52 (mode);
|
||||||
|
|
||||||
|
@ -19539,7 +19545,7 @@ ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
|
||||||
emit_move_insn (res, operand1);
|
emit_move_insn (res, operand1);
|
||||||
|
|
||||||
/* xa = abs (operand1) */
|
/* xa = abs (operand1) */
|
||||||
xa = ix86_expand_sse_fabs (res, NULL);
|
xa = ix86_expand_sse_fabs (res, &mask);
|
||||||
|
|
||||||
/* if (!isless (xa, TWO52)) goto label; */
|
/* if (!isless (xa, TWO52)) goto label; */
|
||||||
label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
|
label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
|
||||||
|
@ -19559,6 +19565,9 @@ ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
|
||||||
expand_simple_binop (mode, do_floor ? MINUS : PLUS,
|
expand_simple_binop (mode, do_floor ? MINUS : PLUS,
|
||||||
xa, tmp, res, 0, OPTAB_DIRECT);
|
xa, tmp, res, 0, OPTAB_DIRECT);
|
||||||
|
|
||||||
|
if (HONOR_SIGNED_ZEROS (mode))
|
||||||
|
ix86_sse_copysign_to_positive (res, res, force_reg (mode, operand1), mask);
|
||||||
|
|
||||||
emit_label (label);
|
emit_label (label);
|
||||||
LABEL_NUSES (label) = 1;
|
LABEL_NUSES (label) = 1;
|
||||||
|
|
||||||
|
@ -19650,10 +19659,13 @@ ix86_expand_trunc (rtx operand0, rtx operand1)
|
||||||
double xa = fabs (x), x2;
|
double xa = fabs (x), x2;
|
||||||
if (!isless (xa, TWO52))
|
if (!isless (xa, TWO52))
|
||||||
return x;
|
return x;
|
||||||
return (double)(long)x;
|
x2 = (double)(long)x;
|
||||||
|
if (HONOR_SIGNED_ZEROS (mode))
|
||||||
|
return copysign (x2, x);
|
||||||
|
return x2;
|
||||||
*/
|
*/
|
||||||
enum machine_mode mode = GET_MODE (operand0);
|
enum machine_mode mode = GET_MODE (operand0);
|
||||||
rtx xa, xi, TWO52, label, res;
|
rtx xa, xi, TWO52, label, res, mask;
|
||||||
|
|
||||||
TWO52 = ix86_gen_TWO52 (mode);
|
TWO52 = ix86_gen_TWO52 (mode);
|
||||||
|
|
||||||
|
@ -19663,7 +19675,7 @@ ix86_expand_trunc (rtx operand0, rtx operand1)
|
||||||
emit_move_insn (res, operand1);
|
emit_move_insn (res, operand1);
|
||||||
|
|
||||||
/* xa = abs (operand1) */
|
/* xa = abs (operand1) */
|
||||||
xa = ix86_expand_sse_fabs (res, NULL);
|
xa = ix86_expand_sse_fabs (res, &mask);
|
||||||
|
|
||||||
/* if (!isless (xa, TWO52)) goto label; */
|
/* if (!isless (xa, TWO52)) goto label; */
|
||||||
label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
|
label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
|
||||||
|
@ -19673,6 +19685,9 @@ ix86_expand_trunc (rtx operand0, rtx operand1)
|
||||||
expand_fix (xi, res, 0);
|
expand_fix (xi, res, 0);
|
||||||
expand_float (res, xi, 0);
|
expand_float (res, xi, 0);
|
||||||
|
|
||||||
|
if (HONOR_SIGNED_ZEROS (mode))
|
||||||
|
ix86_sse_copysign_to_positive (res, res, force_reg (mode, operand1), mask);
|
||||||
|
|
||||||
emit_label (label);
|
emit_label (label);
|
||||||
LABEL_NUSES (label) = 1;
|
LABEL_NUSES (label) = 1;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
2006-11-01 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
|
* testsuite/gcc.target/i386/fpprec-1.c: New testcase.
|
||||||
|
|
||||||
2006-11-01 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
2006-11-01 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||||
|
|
||||||
* gcc.dg/torture/builtin-attr-1.c: Don't test gamma/lgamma.
|
* gcc.dg/torture/builtin-attr-1.c: Don't test gamma/lgamma.
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-options "-O2 -fno-math-errno -fno-trapping-math -msse2 -mfpmath=sse" } */
|
||||||
|
|
||||||
|
#include "../../gcc.dg/i386-cpuid.h"
|
||||||
|
|
||||||
|
extern void abort(void);
|
||||||
|
extern int printf(const char *format, ...);
|
||||||
|
|
||||||
|
double x[] = { __builtin_nan(""), __builtin_inf(), -__builtin_inf(),
|
||||||
|
-0x1.fffffffffffffp+1023, 0x1.fffffffffffffp+1023, /* +-DBL_MAX */
|
||||||
|
-0x1p-52, 0x1p-52, /* +-DBL_EPSILON */
|
||||||
|
/* nextafter/before 0.5, 1.0 and 1.5 */
|
||||||
|
0x1.0000000000001p-1, 0x1.fffffffffffffp-2,
|
||||||
|
0x1.0000000000001p+0, 0x1.fffffffffffffp-1,
|
||||||
|
0x1.8000000000001p+0, 0x1.7ffffffffffffp+0,
|
||||||
|
-0.0, 0.0, -0.5, 0.5, -1.0, 1.0, -1.5, 1.5, -2.0, 2.0,
|
||||||
|
-2.5, 2.5 };
|
||||||
|
#define NUM (sizeof(x)/sizeof(double))
|
||||||
|
|
||||||
|
double expect_round[] = { __builtin_nan(""), __builtin_inf(), -__builtin_inf(),
|
||||||
|
-0x1.fffffffffffffp+1023, 0x1.fffffffffffffp+1023,
|
||||||
|
-0.0, 0.0,
|
||||||
|
1.0, 0.0, 1.0, 1.0, 2.0, 1.0,
|
||||||
|
-0.0, 0.0, -1.0, 1.0, -1.0, 1.0, -2.0, 2.0, -2.0, 2.0,
|
||||||
|
-3.0, 3.0 };
|
||||||
|
|
||||||
|
double expect_rint[] = { __builtin_nan(""), __builtin_inf(), -__builtin_inf(),
|
||||||
|
-0x1.fffffffffffffp+1023, 0x1.fffffffffffffp+1023,
|
||||||
|
-0.0, 0.0,
|
||||||
|
1.0, 0.0, 1.0, 1.0, 2.0, 1.0,
|
||||||
|
-0.0, 0.0, -0.0, 0.0, -1.0, 1.0, -2.0, 2.0, -2.0, 2.0,
|
||||||
|
-2.0, 2.0 };
|
||||||
|
|
||||||
|
double expect_floor[] = { __builtin_nan(""), __builtin_inf(), -__builtin_inf(),
|
||||||
|
-0x1.fffffffffffffp+1023, 0x1.fffffffffffffp+1023,
|
||||||
|
-1.0, 0.0,
|
||||||
|
0.0, 0.0, 1.0, 0.0, 1.0, 1.0,
|
||||||
|
-0.0, 0.0, -1.0, 0.0, -1.0, 1.0, -2.0, 1.0, -2.0, 2.0,
|
||||||
|
-3.0, 2.0 };
|
||||||
|
|
||||||
|
double expect_ceil[] = { __builtin_nan(""), __builtin_inf(), -__builtin_inf(),
|
||||||
|
-0x1.fffffffffffffp+1023, 0x1.fffffffffffffp+1023,
|
||||||
|
-0.0, 1.0,
|
||||||
|
1.0, 1.0, 2.0, 1.0, 2.0, 2.0,
|
||||||
|
-0.0, 0.0, -0.0, 1.0, -1.0, 1.0, -1.0, 2.0, -2.0, 2.0,
|
||||||
|
-2.0, 3.0 };
|
||||||
|
|
||||||
|
double expect_trunc[] = { __builtin_nan(""), __builtin_inf(), -__builtin_inf(),
|
||||||
|
-0x1.fffffffffffffp+1023, 0x1.fffffffffffffp+1023,
|
||||||
|
-0.0, 0.0,
|
||||||
|
0.0, 0.0, 1.0, 0.0, 1.0, 1.0,
|
||||||
|
-0.0, 0.0, -0.0, 0.0, -1.0, 1.0, -1.0, 1.0, -2.0, 2.0,
|
||||||
|
-2.0, 2.0 };
|
||||||
|
|
||||||
|
|
||||||
|
#define CHECK(fn) \
|
||||||
|
void check_ ## fn (void) \
|
||||||
|
{ \
|
||||||
|
int i; \
|
||||||
|
for (i = 0; i < NUM; ++i) \
|
||||||
|
{ \
|
||||||
|
double res = __builtin_ ## fn (x[i]); \
|
||||||
|
if (__builtin_memcmp (&res, &expect_ ## fn [i], sizeof(double)) != 0) \
|
||||||
|
printf( # fn " [%i]: %.18e %.18e\n", i, expect_ ## fn [i], res), abort (); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK(round)
|
||||||
|
CHECK(rint)
|
||||||
|
CHECK(floor)
|
||||||
|
CHECK(ceil)
|
||||||
|
CHECK(trunc)
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
unsigned long cpu_facilities;
|
||||||
|
|
||||||
|
cpu_facilities = i386_cpuid ();
|
||||||
|
|
||||||
|
if ((cpu_facilities & bit_SSE2) != bit_SSE2)
|
||||||
|
/* If host has no SSE2 support, pass. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
check_round ();
|
||||||
|
check_rint ();
|
||||||
|
check_floor ();
|
||||||
|
check_ceil ();
|
||||||
|
check_trunc ();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue