mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-27 10:03:58 +08:00
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
This commit is contained in:
parent
e3e9f10846
commit
bc9ec0e06b
@ -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.
|
||||
|
||||
|
@ -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)));
|
||||
|
@ -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>
|
||||
|
141
gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-8.c
Normal file
141
gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-8.c
Normal file
@ -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);
|
||||
}
|
80
gcc/testsuite/gcc.dg/ppc-fsel-2.c
Normal file
80
gcc/testsuite/gcc.dg/ppc-fsel-2.c
Normal file
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user