Commit bc9ec0e0 by Geoffrey Keating Committed by Geoffrey Keating

rs6000.c (validate_condition_mode): Use flag_finite_math_only.

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.

From-SVN: r66499
parent e3e9f108
...@@ -22,6 +22,15 @@ ...@@ -22,6 +22,15 @@
2003-05-05 Geoffrey Keating <geoffk@apple.com> 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 * toplev.c (check_global_declarations): Suppress not-used warning
for volatile variables. for volatile variables.
......
...@@ -7191,9 +7191,8 @@ validate_condition_mode (code, mode) ...@@ -7191,9 +7191,8 @@ validate_condition_mode (code, mode)
abort (); abort ();
/* These should never be generated except for /* These should never be generated except for
flag_unsafe_math_optimizations and flag_finite_math_only. */ flag_finite_math_only. */
if (mode == CCFPmode if (mode == CCFPmode
&& ! flag_unsafe_math_optimizations
&& ! flag_finite_math_only && ! flag_finite_math_only
&& (code == LE || code == GE && (code == LE || code == GE
|| code == UNEQ || code == LTGT || code == UNEQ || code == LTGT
...@@ -8637,7 +8636,10 @@ rs6000_reverse_condition (mode, code) ...@@ -8637,7 +8636,10 @@ rs6000_reverse_condition (mode, code)
{ {
/* Reversal of FP compares takes care -- an ordered compare /* Reversal of FP compares takes care -- an ordered compare
becomes an unordered compare and vice versa. */ 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); return reverse_condition_maybe_unordered (code);
else else
return reverse_condition (code); return reverse_condition (code);
...@@ -8676,7 +8678,7 @@ rs6000_generate_compare (code) ...@@ -8676,7 +8678,7 @@ rs6000_generate_compare (code)
case UNEQ: case UNEQ:
case NE: case NE:
case LTGT: case LTGT:
cmp = flag_unsafe_math_optimizations cmp = flag_finite_math_only
? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0, ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1) rs6000_compare_op1)
: gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0, : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
...@@ -8688,7 +8690,7 @@ rs6000_generate_compare (code) ...@@ -8688,7 +8690,7 @@ rs6000_generate_compare (code)
case UNGE: case UNGE:
case GE: case GE:
case GEU: case GEU:
cmp = flag_unsafe_math_optimizations cmp = flag_finite_math_only
? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0, ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1) rs6000_compare_op1)
: gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0, : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
...@@ -8700,7 +8702,7 @@ rs6000_generate_compare (code) ...@@ -8700,7 +8702,7 @@ rs6000_generate_compare (code)
case UNLE: case UNLE:
case LE: case LE:
case LEU: case LEU:
cmp = flag_unsafe_math_optimizations cmp = flag_finite_math_only
? gen_tstsflt_gpr (compare_result, rs6000_compare_op0, ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1) rs6000_compare_op1)
: gen_cmpsflt_gpr (compare_result, rs6000_compare_op0, : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0,
...@@ -8732,7 +8734,7 @@ rs6000_generate_compare (code) ...@@ -8732,7 +8734,7 @@ rs6000_generate_compare (code)
compare_result2 = gen_reg_rtx (CCFPmode); compare_result2 = gen_reg_rtx (CCFPmode);
/* Do the EQ. */ /* Do the EQ. */
cmp = flag_unsafe_math_optimizations cmp = flag_finite_math_only
? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0, ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0,
rs6000_compare_op1) rs6000_compare_op1)
: gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0, : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0,
...@@ -8788,9 +8790,9 @@ rs6000_generate_compare (code) ...@@ -8788,9 +8790,9 @@ rs6000_generate_compare (code)
rs6000_compare_op1))); rs6000_compare_op1)));
/* Some kinds of FP comparisons need an OR operation; /* 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 if (rs6000_compare_fp_p
&& ! flag_unsafe_math_optimizations && ! flag_finite_math_only
&& ! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS) && ! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)
&& (code == LE || code == GE && (code == LE || code == GE
|| code == UNEQ || code == LTGT || code == UNEQ || code == LTGT
...@@ -9069,7 +9071,7 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond) ...@@ -9069,7 +9071,7 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
/* Eliminate half of the comparisons by switching operands, this /* Eliminate half of the comparisons by switching operands, this
makes the remaining code simpler. */ makes the remaining code simpler. */
if (code == UNLT || code == UNGT || code == UNORDERED || code == NE 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); code = reverse_condition_maybe_unordered (code);
temp = true_cond; temp = true_cond;
...@@ -9079,7 +9081,7 @@ rs6000_emit_cmove (dest, op, true_cond, false_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, /* UNEQ and LTGT take four instructions for a comparison with zero,
it'll probably be faster to use a branch here too. */ it'll probably be faster to use a branch here too. */
if (code == UNEQ) if (code == UNEQ && HONOR_NANS (compare_mode))
return 0; return 0;
if (GET_CODE (op1) == CONST_DOUBLE) if (GET_CODE (op1) == CONST_DOUBLE)
...@@ -9090,7 +9092,7 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond) ...@@ -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 Inf - Inf is NaN which is not zero, and so if we don't
know that the operand is finite and the comparison know that the operand is finite and the comparison
would treat EQ different to UNORDERED, we can't do it. */ 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 && code != GT && code != UNGE
&& (GET_CODE (op1) != CONST_DOUBLE || real_isinf (&c1)) && (GET_CODE (op1) != CONST_DOUBLE || real_isinf (&c1))
/* Constructs of the form (a OP b ? a : b) are safe. */ /* Constructs of the form (a OP b ? a : b) are safe. */
...@@ -9109,7 +9111,7 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond) ...@@ -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 /* If we don't care about NaNs we can reduce some of the comparisons
down to faster ones. */ down to faster ones. */
if (flag_unsafe_math_optimizations) if (! HONOR_NANS (compare_mode))
switch (code) switch (code)
{ {
case GT: case GT:
...@@ -9155,14 +9157,15 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond) ...@@ -9155,14 +9157,15 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
break; break;
case UNGE: case UNGE:
/* a UNGE 0 <-> (a GE 0 || -a UNLT 0) */
temp = gen_reg_rtx (result_mode); temp = gen_reg_rtx (result_mode);
emit_insn (gen_rtx_SET (VOIDmode, temp, emit_insn (gen_rtx_SET (VOIDmode, temp,
gen_rtx_IF_THEN_ELSE (result_mode, gen_rtx_IF_THEN_ELSE (result_mode,
gen_rtx_GE (VOIDmode, gen_rtx_GE (VOIDmode,
op0, op1), op0, op1),
true_cond, false_cond))); true_cond, false_cond)));
false_cond = temp; false_cond = true_cond;
true_cond = false_cond; true_cond = temp;
temp = gen_reg_rtx (compare_mode); temp = gen_reg_rtx (compare_mode);
emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0))); 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) ...@@ -9170,14 +9173,15 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
break; break;
case GT: case GT:
/* a GT 0 <-> (a GE 0 && -a UNLT 0) */
temp = gen_reg_rtx (result_mode); temp = gen_reg_rtx (result_mode);
emit_insn (gen_rtx_SET (VOIDmode, temp, emit_insn (gen_rtx_SET (VOIDmode, temp,
gen_rtx_IF_THEN_ELSE (result_mode, gen_rtx_IF_THEN_ELSE (result_mode,
gen_rtx_GE (VOIDmode, gen_rtx_GE (VOIDmode,
op0, op1), op0, op1),
true_cond, false_cond))); true_cond, false_cond)));
true_cond = temp; true_cond = false_cond;
false_cond = true_cond; false_cond = temp;
temp = gen_reg_rtx (compare_mode); temp = gen_reg_rtx (compare_mode);
emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0))); emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0)));
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
2003-05-05 Geoffrey Keating <geoffk@apple.com> 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. * gcc.dg/unused-5.c: New test.
2003-05-05 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> 2003-05-05 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
......
/* 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);
}
/* { 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;
}
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