+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,
{
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. */
}
}
+ 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;
break;
}
- comp_mode = SImode;
- op_mode = GET_MODE (spu_compare_op0);
-
switch (op_mode)
{
case QImode:
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)
+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.
--- /dev/null
+/* { 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);
+}