> I'm okay with most of the change, but I have a question: What happened
> to the unsigned comparisons and LTGT?
Unsigned comparisons aren't used for FP (the whole block of code is dominated
by a FLOAT_MODE_P (mode) test). LTGT and UNEQ were wrong (but unused) since
they were implemented as NE and EQ respectively and therefore didn't return
the correct result for NaNs. In fact, all the unordered operators were wrong
(but unused) since they were implemented as their ordered counterpart.
> I'm not going to insist, but this probably deserves an e500-specific
> testcase that it's generating the correct results and not calling
> libgcc for unordered comparisons.
Note that, for originally unordered comparisons, there has always been a call
to libgcc as rs6000_cbranch_operator is ordered_comparison_operator on e500
(hence the wrong implementation in rs6000_generate_compare was unused). But,
indeed, we should verify that we don't generate them when the comparisons are
originally ordered, with and without -ftrapping-math.
I have attached 4 testcases:
- e500-ord-1.c: ordered/signaling predicates, -ftrapping-math
- e500-ord-2.c: ordered/signaling predicates, -fno-trapping-math
- e500-unord-1.c: C99 unordered/quiet predicates, -ftrapping-math
- e500-unord-2.c: C99 unordered/quiet predicates, -fno-trapping-math
With the unpatched compiler:
- e500-ord-1.c: no calls to __unordsf2 (optimal)
- e500-ord-2.c: calls to __unordsf2 (the very issue I'm fixing)
- e500-unord-1.c: calls to __unordsf2 (optimal)
- e500-unord-2.c: calls to __unordsf2 (useless since -fno-trapping-math)
With the patched compiler:
- e500-ord-1.c: no calls to __unordsf2 (optimal)
- e500-ord-2.c: no calls to __unordsf2 (optimal)
- e500-unord-1.c: calls to __unordsf2 (optimal)
- e500-unord-2.c: no calls to __unordsf2 (optimal)
2013-05-31 Eric Botcazou <ebotca...@adacore.com>
* gcc.target/powerpc/e500-ord-1.c: New test.
* gcc.target/powerpc/e500-ord-2.c: Likewise.
* gcc.target/powerpc/e500-unord-1.c: Likewise.
* gcc.target/powerpc/e500-unord-2.c: Likewise.
--
Eric Botcazou
/* { dg-do compile { target powerpc*-*-eabi* } } */
/* { dg-options "-O -ftrapping-math -fdump-rtl-final" } */
int isgreater (float f1, float f2)
{
int r = (f1 > f2);
return !r ? -1 : 1;
}
int isgreaterequal (float f1, float f2)
{
int r = (f1 >= f2);
return !r ? -1 : 1;
}
int isless (float f1, float f2)
{
int r = (f1 < f2);
return !r ? -1 : 1;
}
int islessequal (float f1, float f2)
{
int r = (f1 <= f2);
return !r ? -1 : 1;
}
/* { dg-final { scan-rtl-dump-not "__unordsf2" "final" } } */
/* { dg-final { cleanup-rtl-dump "final" } } */
/* { dg-do compile { target powerpc*-*-eabi* } } */
/* { dg-options "-O -fno-trapping-math -fdump-rtl-final" } */
int isgreater (float f1, float f2)
{
int r = (f1 > f2);
return !r ? -1 : 1;
}
int isgreaterequal (float f1, float f2)
{
int r = (f1 >= f2);
return !r ? -1 : 1;
}
int isless (float f1, float f2)
{
int r = (f1 < f2);
return !r ? -1 : 1;
}
int islessequal (float f1, float f2)
{
int r = (f1 <= f2);
return !r ? -1 : 1;
}
/* { dg-final { scan-rtl-dump-not "__unordsf2" "final" } } */
/* { dg-final { cleanup-rtl-dump "final" } } */
/* { dg-do compile { target powerpc*-*-eabi* } } */
/* { dg-options "-O -ftrapping-math -fdump-rtl-final" } */
int isgreater (float f1, float f2)
{
int r = __builtin_isgreater (f1, f2);
return !r ? -1 : 1;
}
int isgreaterequal (float f1, float f2)
{
int r = __builtin_isgreaterequal (f1, f2);
return !r ? -1 : 1;
}
int isless (float f1, float f2)
{
int r = __builtin_isless (f1, f2);
return !r ? -1 : 1;
}
int islessequal (float f1, float f2)
{
int r = __builtin_islessequal (f1, f2);
return !r ? -1 : 1;
}
/* { dg-final { scan-rtl-dump-times "__unordsf2" 4 "final" } } */
/* { dg-final { cleanup-rtl-dump "final" } } */
/* { dg-do compile { target powerpc*-*-eabi* } } */
/* { dg-options "-O -fno-trapping-math -fdump-rtl-final" } */
int isgreater (float f1, float f2)
{
int r = __builtin_isgreater (f1, f2);
return !r ? -1 : 1;
}
int isgreaterequal (float f1, float f2)
{
int r = __builtin_isgreaterequal (f1, f2);
return !r ? -1 : 1;
}
int isless (float f1, float f2)
{
int r = __builtin_isless (f1, f2);
return !r ? -1 : 1;
}
int islessequal (float f1, float f2)
{
int r = __builtin_islessequal (f1, f2);
return !r ? -1 : 1;
}
/* { dg-final { scan-rtl-dump-not "__unordsf2" "final" } } */
/* { dg-final { cleanup-rtl-dump "final" } } */