predicates.md (rs6000_cbranch_operator): Accept some unordered comparison operators when...

* config/rs6000/predicates.md (rs6000_cbranch_operator): Accept some
	unordered comparison operators when -fno-trapping-math is in effect
	on the e500.
	* config/rs6000/rs6000.c (rs6000_generate_compare): Remove dead code
	and implement unordered comparison operators properly on the e500.

From-SVN: r199557
This commit is contained in:
Eric Botcazou 2013-05-31 19:12:05 +00:00 committed by Eric Botcazou
parent a8c50132e9
commit 4172215d0a
8 changed files with 175 additions and 23 deletions

View File

@ -1,3 +1,11 @@
2013-05-31 Eric Botcazou <ebotcazou@adacore.com>
* config/rs6000/predicates.md (rs6000_cbranch_operator): Accept some
unordered comparison operators when -fno-trapping-math is in effect
on the e500.
* config/rs6000/rs6000.c (rs6000_generate_compare): Remove dead code
and implement unordered comparison operators properly on the e500.
2013-05-31 Eric Botcazou <ebotcazou@adacore.com>
* simplify-rtx.c (simplify_byte_swapping_operation): Use proper macro

View File

@ -1121,9 +1121,16 @@
GET_MODE (XEXP (op, 0))),
1"))))
;; Return 1 if OP is a valid comparison operator for "cbranch" instructions.
;; If we're assuming that FP operations cannot generate user-visible traps,
;; then on e500 we can use the ordered-signaling instructions to implement
;; the unordered-quiet FP comparison predicates modulo a reversal.
(define_predicate "rs6000_cbranch_operator"
(if_then_else (match_test "TARGET_HARD_FLOAT && !TARGET_FPRS")
(match_operand 0 "ordered_comparison_operator")
(if_then_else (match_test "flag_trapping_math")
(match_operand 0 "ordered_comparison_operator")
(ior (match_operand 0 "ordered_comparison_operator")
(match_code ("unlt,unle,ungt,unge"))))
(match_operand 0 "comparison_operator")))
;; Return 1 if OP is a comparison operation that is valid for an SCC insn --

View File

@ -16087,16 +16087,41 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode)
{
rtx cmp, or_result, compare_result2;
enum machine_mode op_mode = GET_MODE (op0);
bool reverse_p;
if (op_mode == VOIDmode)
op_mode = GET_MODE (op1);
/* First reverse the condition codes that aren't directly supported. */
switch (code)
{
case NE:
case UNLT:
case UNLE:
case UNGT:
case UNGE:
code = reverse_condition_maybe_unordered (code);
reverse_p = true;
break;
case EQ:
case LT:
case LE:
case GT:
case GE:
reverse_p = false;
break;
default:
gcc_unreachable ();
}
/* The E500 FP compare instructions toggle the GT bit (CR bit 1) only.
This explains the following mess. */
switch (code)
{
case EQ: case UNEQ: case NE: case LTGT:
case EQ:
switch (op_mode)
{
case SFmode:
@ -16122,7 +16147,8 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode)
}
break;
case GT: case GTU: case UNGT: case UNGE: case GE: case GEU:
case GT:
case GE:
switch (op_mode)
{
case SFmode:
@ -16148,7 +16174,8 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode)
}
break;
case LT: case LTU: case UNLT: case UNLE: case LE: case LEU:
case LT:
case LE:
switch (op_mode)
{
case SFmode:
@ -16173,24 +16200,16 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode)
gcc_unreachable ();
}
break;
default:
gcc_unreachable ();
}
/* Synthesize LE and GE from LT/GT || EQ. */
if (code == LE || code == GE || code == LEU || code == GEU)
if (code == LE || code == GE)
{
emit_insn (cmp);
switch (code)
{
case LE: code = LT; break;
case GE: code = GT; break;
case LEU: code = LT; break;
case GEU: code = GT; break;
default: gcc_unreachable ();
}
compare_result2 = gen_reg_rtx (CCFPmode);
/* Do the EQ. */
@ -16217,23 +16236,18 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode)
default:
gcc_unreachable ();
}
emit_insn (cmp);
/* OR them together. */
or_result = gen_reg_rtx (CCFPmode);
cmp = gen_e500_cr_ior_compare (or_result, compare_result,
compare_result2);
compare_result2);
compare_result = or_result;
code = EQ;
}
else
{
if (code == NE || code == LTGT)
code = NE;
else
code = EQ;
}
code = reverse_p ? NE : EQ;
emit_insn (cmp);
}
else

View File

@ -1,3 +1,10 @@
2013-05-31 Eric Botcazou <ebotcazou@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.
2013-05-31 Marcus Shawcroft <marcus.shawcroft@arm.com>
* g++.dg/torture/pr54684.C: Add -fno-short-enums.

View File

@ -0,0 +1,29 @@
/* { 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" } } */

View File

@ -0,0 +1,29 @@
/* { 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" } } */

View File

@ -0,0 +1,29 @@
/* { 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" } } */

View File

@ -0,0 +1,29 @@
/* { 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" } } */