summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgeoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4>2003-05-05 19:33:52 +0000
committergeoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4>2003-05-05 19:33:52 +0000
commitdebdfaa79e2902428c869612ff05199b9a2f0bb9 (patch)
tree0e5be2a8db71f0d0635751e3cb960ed2c9c73e7b
parent647661c6bb7287179a8b6cc17979102c30e3fbb6 (diff)
downloadppe42-gcc-debdfaa79e2902428c869612ff05199b9a2f0bb9.tar.gz
ppe42-gcc-debdfaa79e2902428c869612ff05199b9a2f0bb9.zip
2003-05-05 Geoffrey Keating <geoffk@apple.com>
* config/rs6000/rs6000.c (validate_condition_mode): Use flag_finite_math_only. (rs6000_reverse_condition): Never return UNKNOWN; use flag_finite_math_only. (rs6000_generate_compare): Use flag_finite_math_only. (rs6000_emit_cmove): Handle UNLE. Support UNEQ under -ffast-math. Use HONOR_* rather than flag_unsafe_math_optimizations. Correct UNGE and GT cases. Handle UNEQ and LTGT when ! HONOR_NANS. Index: testsuite/ChangeLog 2003-05-05 Geoffrey Keating <geoffk@apple.com> * gcc.c-torture/execute/ieee/fp-cmp-8.c: New test. * gcc.dg/ppc-fsel-2.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@66499 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/rs6000/rs6000.c38
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-8.c141
-rw-r--r--gcc/testsuite/gcc.dg/ppc-fsel-2.c80
5 files changed, 254 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0b57087b438..573ec59e6e7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -22,6 +22,15 @@
2003-05-05 Geoffrey Keating <geoffk@apple.com>
+ * config/rs6000/rs6000.c (validate_condition_mode): Use
+ flag_finite_math_only.
+ (rs6000_reverse_condition): Never return UNKNOWN; use
+ flag_finite_math_only.
+ (rs6000_generate_compare): Use flag_finite_math_only.
+ (rs6000_emit_cmove): Handle UNLE. Support UNEQ under -ffast-math.
+ Use HONOR_* rather than flag_unsafe_math_optimizations. Correct
+ UNGE and GT cases. Handle UNEQ and LTGT when ! HONOR_NANS.
+
* toplev.c (check_global_declarations): Suppress not-used warning
for volatile variables.
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 695443a0ed5..4847a8572bd 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -7191,9 +7191,8 @@ validate_condition_mode (code, mode)
abort ();
/* These should never be generated except for
- flag_unsafe_math_optimizations and flag_finite_math_only. */
+ flag_finite_math_only. */
if (mode == CCFPmode
- && ! flag_unsafe_math_optimizations
&& ! flag_finite_math_only
&& (code == LE || code == GE
|| code == UNEQ || code == LTGT
@@ -8637,7 +8636,10 @@ rs6000_reverse_condition (mode, code)
{
/* Reversal of FP compares takes care -- an ordered compare
becomes an unordered compare and vice versa. */
- if (mode == CCFPmode && !flag_unsafe_math_optimizations)
+ if (mode == CCFPmode
+ && (!flag_finite_math_only
+ || code == UNLT || code == UNLE || code == UNGT || code == UNGE
+ || code == UNEQ || code == LTGT))
return reverse_condition_maybe_unordered (code);
else
return reverse_condition (code);
@@ -8676,7 +8678,7 @@ rs6000_generate_compare (code)
case UNEQ:
case NE:
case LTGT:
- cmp = flag_unsafe_math_optimizations
+ cmp = flag_finite_math_only
? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1)
: gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
@@ -8688,7 +8690,7 @@ rs6000_generate_compare (code)
case UNGE:
case GE:
case GEU:
- cmp = flag_unsafe_math_optimizations
+ cmp = flag_finite_math_only
? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1)
: gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
@@ -8700,7 +8702,7 @@ rs6000_generate_compare (code)
case UNLE:
case LE:
case LEU:
- cmp = flag_unsafe_math_optimizations
+ cmp = flag_finite_math_only
? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1)
: gen_cmpsflt_gpr (compare_result, rs6000_compare_op0,
@@ -8732,7 +8734,7 @@ rs6000_generate_compare (code)
compare_result2 = gen_reg_rtx (CCFPmode);
/* Do the EQ. */
- cmp = flag_unsafe_math_optimizations
+ cmp = flag_finite_math_only
? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0,
rs6000_compare_op1)
: gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0,
@@ -8788,9 +8790,9 @@ rs6000_generate_compare (code)
rs6000_compare_op1)));
/* Some kinds of FP comparisons need an OR operation;
- except for flag_unsafe_math_optimizations we don't bother. */
+ under flag_finite_math_only we don't bother. */
if (rs6000_compare_fp_p
- && ! flag_unsafe_math_optimizations
+ && ! flag_finite_math_only
&& ! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)
&& (code == LE || code == GE
|| code == UNEQ || code == LTGT
@@ -9069,7 +9071,7 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
/* Eliminate half of the comparisons by switching operands, this
makes the remaining code simpler. */
if (code == UNLT || code == UNGT || code == UNORDERED || code == NE
- || code == LTGT || code == LT)
+ || code == LTGT || code == LT || code == UNLE)
{
code = reverse_condition_maybe_unordered (code);
temp = true_cond;
@@ -9079,7 +9081,7 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
/* UNEQ and LTGT take four instructions for a comparison with zero,
it'll probably be faster to use a branch here too. */
- if (code == UNEQ)
+ if (code == UNEQ && HONOR_NANS (compare_mode))
return 0;
if (GET_CODE (op1) == CONST_DOUBLE)
@@ -9090,7 +9092,7 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
Inf - Inf is NaN which is not zero, and so if we don't
know that the operand is finite and the comparison
would treat EQ different to UNORDERED, we can't do it. */
- if (! flag_unsafe_math_optimizations
+ if (HONOR_INFINITIES (compare_mode)
&& code != GT && code != UNGE
&& (GET_CODE (op1) != CONST_DOUBLE || real_isinf (&c1))
/* Constructs of the form (a OP b ? a : b) are safe. */
@@ -9109,7 +9111,7 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
/* If we don't care about NaNs we can reduce some of the comparisons
down to faster ones. */
- if (flag_unsafe_math_optimizations)
+ if (! HONOR_NANS (compare_mode))
switch (code)
{
case GT:
@@ -9155,14 +9157,15 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
break;
case UNGE:
+ /* a UNGE 0 <-> (a GE 0 || -a UNLT 0) */
temp = gen_reg_rtx (result_mode);
emit_insn (gen_rtx_SET (VOIDmode, temp,
gen_rtx_IF_THEN_ELSE (result_mode,
gen_rtx_GE (VOIDmode,
op0, op1),
true_cond, false_cond)));
- false_cond = temp;
- true_cond = false_cond;
+ false_cond = true_cond;
+ true_cond = temp;
temp = gen_reg_rtx (compare_mode);
emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0)));
@@ -9170,14 +9173,15 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
break;
case GT:
+ /* a GT 0 <-> (a GE 0 && -a UNLT 0) */
temp = gen_reg_rtx (result_mode);
emit_insn (gen_rtx_SET (VOIDmode, temp,
gen_rtx_IF_THEN_ELSE (result_mode,
gen_rtx_GE (VOIDmode,
op0, op1),
true_cond, false_cond)));
- true_cond = temp;
- false_cond = true_cond;
+ true_cond = false_cond;
+ false_cond = temp;
temp = gen_reg_rtx (compare_mode);
emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0)));
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 536043aba92..90eb31bd8c3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -4,6 +4,9 @@
2003-05-05 Geoffrey Keating <geoffk@apple.com>
+ * gcc.c-torture/execute/ieee/fp-cmp-8.c: New test.
+ * gcc.dg/ppc-fsel-2.c: New test.
+
* gcc.dg/unused-5.c: New test.
2003-05-05 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-8.c b/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-8.c
new file mode 100644
index 00000000000..225539b83eb
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-8.c
@@ -0,0 +1,141 @@
+/* Like fp-cmp-4.c, but test that the cmove patterns are correct. */
+
+static double
+test_isunordered(double x, double y, double a, double b)
+{
+ return __builtin_isunordered(x, y) ? a : b;
+}
+
+static double
+test_not_isunordered(double x, double y, double a, double b)
+{
+ return !__builtin_isunordered(x, y) ? a : b;
+}
+
+static double
+test_isless(double x, double y, double a, double b)
+{
+ return __builtin_isless(x, y) ? a : b;
+}
+
+static double
+test_not_isless(double x, double y, double a, double b)
+{
+ return !__builtin_isless(x, y) ? a : b;
+}
+
+static double
+test_islessequal(double x, double y, double a, double b)
+{
+ return __builtin_islessequal(x, y) ? a : b;
+}
+
+static double
+test_not_islessequal(double x, double y, double a, double b)
+{
+ return !__builtin_islessequal(x, y) ? a : b;
+}
+
+static double
+test_isgreater(double x, double y, double a, double b)
+{
+ return __builtin_isgreater(x, y) ? a : b;
+}
+
+static double
+test_not_isgreater(double x, double y, double a, double b)
+{
+ return !__builtin_isgreater(x, y) ? a : b;
+}
+
+static double
+test_isgreaterequal(double x, double y, double a, double b)
+{
+ return __builtin_isgreaterequal(x, y) ? a : b;
+}
+
+static double
+test_not_isgreaterequal(double x, double y, double a, double b)
+{
+ return !__builtin_isgreaterequal(x, y) ? a : b;
+}
+
+static double
+test_islessgreater(double x, double y, double a, double b)
+{
+ return __builtin_islessgreater(x, y) ? a : b;
+}
+
+static double
+test_not_islessgreater(double x, double y, double a, double b)
+{
+ return !__builtin_islessgreater(x, y) ? a : b;
+}
+
+static void
+one_test(double x, double y, int expected,
+ double (*pos) (double, double, double, double),
+ double (*neg) (double, double, double, double))
+{
+ if (((*pos)(x, y, 1.0, 2.0) == 1.0) != expected)
+ abort ();
+ if (((*neg)(x, y, 3.0, 4.0) == 4.0) != expected)
+ abort ();
+}
+
+#define NAN (0.0 / 0.0)
+#define INF (1.0 / 0.0)
+
+int
+main()
+{
+ struct try
+ {
+ double x, y;
+ int result[6];
+ };
+
+ static struct try const data[] =
+ {
+ { NAN, NAN, { 1, 0, 0, 0, 0, 0 } },
+ { 0.0, NAN, { 1, 0, 0, 0, 0, 0 } },
+ { NAN, 0.0, { 1, 0, 0, 0, 0, 0 } },
+ { 0.0, 0.0, { 0, 0, 1, 0, 1, 0 } },
+ { 1.0, 2.0, { 0, 1, 1, 0, 0, 1 } },
+ { 2.0, 1.0, { 0, 0, 0, 1, 1, 1 } },
+ { INF, 0.0, { 0, 0, 0, 1, 1, 1 } },
+ { 1.0, INF, { 0, 1, 1, 0, 0, 1 } },
+ { INF, INF, { 0, 0, 1, 0, 1, 0 } },
+ { 0.0, -INF, { 0, 0, 0, 1, 1, 1 } },
+ { -INF, 1.0, { 0, 1, 1, 0, 0, 1 } },
+ { -INF, -INF, { 0, 0, 1, 0, 1, 0 } },
+ { INF, -INF, { 0, 0, 0, 1, 1, 1 } },
+ { -INF, INF, { 0, 1, 1, 0, 0, 1 } },
+ };
+
+ struct test
+ {
+ double (*pos)(double, double, double, double);
+ double (*neg)(double, double, double, double);
+ };
+
+ static struct test const tests[] =
+ {
+ { test_isunordered, test_not_isunordered },
+ { test_isless, test_not_isless },
+ { test_islessequal, test_not_islessequal },
+ { test_isgreater, test_not_isgreater },
+ { test_isgreaterequal, test_not_isgreaterequal },
+ { test_islessgreater, test_not_islessgreater }
+ };
+
+ const int n = sizeof(data) / sizeof(data[0]);
+ int i, j;
+
+ for (i = 0; i < n; ++i)
+ for (j = 0; j < 6; ++j)
+ one_test (data[i].x, data[i].y, data[i].result[j],
+ tests[j].pos, tests[j].neg);
+
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/ppc-fsel-2.c b/gcc/testsuite/gcc.dg/ppc-fsel-2.c
new file mode 100644
index 00000000000..9768b165c24
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ppc-fsel-2.c
@@ -0,0 +1,80 @@
+/* { dg-do compile { target powerpc*-*-* } } */
+/* { dg-options "-O -mpowerpc-gfxopt -g0 -ffinite-math-only" } */
+/* { dg-final { scan-assembler-not "^L" } } */
+
+/* Every single one of these should be compiled into straight-line
+ code using fsel (or, in a few cases, hardwired to 'true' or
+ 'false'), no branches anywhere. */
+
+double
+test_isunordered(double x, double y, double a, double b)
+{
+ return __builtin_isunordered(x, y) ? a : b;
+}
+
+double
+test_not_isunordered(double x, double y, double a, double b)
+{
+ return !__builtin_isunordered(x, y) ? a : b;
+}
+
+double
+test_isless(double x, double y, double a, double b)
+{
+ return __builtin_isless(x, y) ? a : b;
+}
+
+double
+test_not_isless(double x, double y, double a, double b)
+{
+ return !__builtin_isless(x, y) ? a : b;
+}
+
+double
+test_islessequal(double x, double y, double a, double b)
+{
+ return __builtin_islessequal(x, y) ? a : b;
+}
+
+double
+test_not_islessequal(double x, double y, double a, double b)
+{
+ return !__builtin_islessequal(x, y) ? a : b;
+}
+
+double
+test_isgreater(double x, double y, double a, double b)
+{
+ return __builtin_isgreater(x, y) ? a : b;
+}
+
+double
+test_not_isgreater(double x, double y, double a, double b)
+{
+ return !__builtin_isgreater(x, y) ? a : b;
+}
+
+double
+test_isgreaterequal(double x, double y, double a, double b)
+{
+ return __builtin_isgreaterequal(x, y) ? a : b;
+}
+
+double
+test_not_isgreaterequal(double x, double y, double a, double b)
+{
+ return !__builtin_isgreaterequal(x, y) ? a : b;
+}
+
+double
+test_islessgreater(double x, double y, double a, double b)
+{
+ return __builtin_islessgreater(x, y) ? a : b;
+}
+
+double
+test_not_islessgreater(double x, double y, double a, double b)
+{
+ return !__builtin_islessgreater(x, y) ? a : b;
+}
+
OpenPOWER on IntegriCloud