spu.c (spu_emit_branch_or_set): Handle NaN values as operands to DFmode GE or LE compares.
* config/spu/spu.c (spu_emit_branch_or_set): Handle NaN values as operands to DFmode GE or LE compares. testsuite/ * gcc.target/spu/dfcgt-nan.c: New test. From-SVN: r128404
This commit is contained in:
parent
c592621442
commit
9943eb0be3
4 changed files with 86 additions and 10 deletions
|
@ -1,3 +1,8 @@
|
|||
2007-09-12 Sa Liu <saliu@de.ibm.com>
|
||||
|
||||
* config/spu/spu.c (spu_emit_branch_or_set): Handle NaN values as
|
||||
operands to DFmode GE or LE compares.
|
||||
|
||||
2007-09-12 Bernd Schmidt <bernd.schmidt@analog.com>
|
||||
|
||||
* config/bfin/bfin.h (enum reg_class, REG_CLASS_CONTENTS,
|
||||
|
|
|
@ -720,13 +720,14 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
|
|||
{
|
||||
int reverse_compare = 0;
|
||||
int reverse_test = 0;
|
||||
rtx compare_result;
|
||||
rtx comp_rtx;
|
||||
rtx compare_result, eq_result;
|
||||
rtx comp_rtx, eq_rtx;
|
||||
rtx target = operands[0];
|
||||
enum machine_mode comp_mode;
|
||||
enum machine_mode op_mode;
|
||||
enum spu_comp_code scode;
|
||||
enum spu_comp_code scode, eq_code, ior_code;
|
||||
int index;
|
||||
int eq_test = 0;
|
||||
|
||||
/* When spu_compare_op1 is a CONST_INT change (X >= C) to (X > C-1),
|
||||
and so on, to keep the constant in operand 1. */
|
||||
|
@ -757,17 +758,40 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
|
|||
}
|
||||
}
|
||||
|
||||
comp_mode = SImode;
|
||||
op_mode = GET_MODE (spu_compare_op0);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case GE:
|
||||
reverse_compare = 1;
|
||||
reverse_test = 1;
|
||||
scode = SPU_GT;
|
||||
if (HONOR_NANS (op_mode) && spu_arch == PROCESSOR_CELLEDP)
|
||||
{
|
||||
reverse_compare = 0;
|
||||
reverse_test = 0;
|
||||
eq_test = 1;
|
||||
eq_code = SPU_EQ;
|
||||
}
|
||||
else
|
||||
{
|
||||
reverse_compare = 1;
|
||||
reverse_test = 1;
|
||||
}
|
||||
break;
|
||||
case LE:
|
||||
reverse_compare = 0;
|
||||
reverse_test = 1;
|
||||
scode = SPU_GT;
|
||||
if (HONOR_NANS (op_mode) && spu_arch == PROCESSOR_CELLEDP)
|
||||
{
|
||||
reverse_compare = 1;
|
||||
reverse_test = 0;
|
||||
eq_test = 1;
|
||||
eq_code = SPU_EQ;
|
||||
}
|
||||
else
|
||||
{
|
||||
reverse_compare = 0;
|
||||
reverse_test = 1;
|
||||
}
|
||||
break;
|
||||
case LT:
|
||||
reverse_compare = 1;
|
||||
|
@ -809,9 +833,6 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
|
|||
break;
|
||||
}
|
||||
|
||||
comp_mode = SImode;
|
||||
op_mode = GET_MODE (spu_compare_op0);
|
||||
|
||||
switch (op_mode)
|
||||
{
|
||||
case QImode:
|
||||
|
@ -916,6 +937,20 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
|
|||
abort ();
|
||||
emit_insn (comp_rtx);
|
||||
|
||||
if (eq_test)
|
||||
{
|
||||
eq_result = gen_reg_rtx (comp_mode);
|
||||
eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result,
|
||||
spu_compare_op0,
|
||||
spu_compare_op1);
|
||||
if (eq_rtx == 0)
|
||||
abort ();
|
||||
emit_insn (eq_rtx);
|
||||
ior_code = ior_optab->handlers[(int)comp_mode].insn_code;
|
||||
gcc_assert (ior_code != CODE_FOR_nothing);
|
||||
emit_insn (GEN_FCN (ior_code)
|
||||
(compare_result, compare_result, eq_result));
|
||||
}
|
||||
}
|
||||
|
||||
if (is_set == 0)
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2007-09-12 Ben Elliston <bje@au.ibm.com>
|
||||
Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* gcc.target/spu/dfcgt-nan.c: New test.
|
||||
|
||||
2007-09-11 Hans-Peter Nilsson <hp@axis.com>
|
||||
|
||||
* gcc.dg/cpp/trad/include.c: Don't run for newlib targets.
|
||||
|
|
31
gcc/testsuite/gcc.target/spu/dfcgt-nan.c
Normal file
31
gcc/testsuite/gcc.target/spu/dfcgt-nan.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-march=celledp -O1" } */
|
||||
/* { dg-final { scan-assembler "dfceq" } } */
|
||||
|
||||
/* GCC previously transformed an "a <= b" test into "! (a > b)" when
|
||||
compiling with -march=celledp, so that the dfcgt instruction can be
|
||||
used to implement the comparison.
|
||||
|
||||
However, this transformation violates the IEEE-754 standard in the
|
||||
presence of NaN values. If either a or b is a NaN, a <= b should
|
||||
evaluate to false according to IEEE rules. However, after the
|
||||
transformation, a > b as implemented by dfcgt itself returns false,
|
||||
so the transformed test returns true.
|
||||
|
||||
Note that the equivalent transformation is valid for single-
|
||||
precision floating-point values on the Cell SPU, because the format
|
||||
does not have NaNs. It is invalid for double-precision, even on
|
||||
Cell, however. */
|
||||
|
||||
int test (double a, double b) __attribute__ ((noinline));
|
||||
int test (double a, double b)
|
||||
{
|
||||
return a <= b;
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
double x = 0.0;
|
||||
double y = 0.0/0.0;
|
||||
return test (x, y);
|
||||
}
|
Loading…
Add table
Reference in a new issue