This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
no fsel when flag_trapping_math on ppc
- From: gkeating at apple dot com (Geoffrey Keating)
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 7 Oct 2004 14:13:37 -0700 (PDT)
- Subject: no fsel when flag_trapping_math on ppc
In code like:
double foo(double a, double b, double c, double d)
{
return a < b ? c : d;
}
GCC would turn this into
return (a - b) < 0 ? c : d
but the 'a-b' might trap, for instance if a == b == +Inf, or on
overflow, when the compare would not have.
An unfortunate side-effect of this patch is that because the inputs to
this routine are actually never constants (because the compare
instruction can't take constants), this completely disables use of
fsel when -ftrapping-math is in effect. I think the best solution to
that in the future is to implement the C99 pragma to control
trapping-math and then switch it off by default.
Bootstrapped & tested on powerpc-darwin.
--
- Geoffrey Keating <geoffk@apple.com>
===File ~/patches/gcc-3813796.patch=========================
2004-10-07 Geoffrey Keating <geoffk@apple.com>
Radar 3813796
* config/rs6000/rs6000.c (rs6000_generate_compare): When
flag_trapping_math is in effect, don't generate subtract
instructions.
Index: testsuite/ChangeLog
2004-10-07 Geoffrey Keating <geoffk@apple.com>
* gcc.dg/ppc-fsel-3.c: New file.
* gcc.dg/ppc-fsel-1.c: Add -fno-trapping-math, update comment.
Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.720
diff -u -p -u -p -r1.720 rs6000.c
--- config/rs6000/rs6000.c 5 Oct 2004 12:43:53 -0000 1.720
+++ config/rs6000/rs6000.c 7 Oct 2004 21:05:16 -0000
@@ -11216,6 +11216,7 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx
enum machine_mode compare_mode = GET_MODE (op0);
enum machine_mode result_mode = GET_MODE (dest);
rtx temp;
+ bool is_against_zero;
/* These modes should always match. */
if (GET_MODE (op1) != compare_mode
@@ -11240,6 +11241,17 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx
&& GET_MODE_CLASS (compare_mode) == MODE_FLOAT)
return 0;
+ is_against_zero = op1 == CONST0_RTX (compare_mode);
+
+ /* A floating-point subtract might overflow, underflow, or produce
+ an inexact result, thus changing the floating-point flags, so it
+ can't be generated if we care about that. It's safe if one side
+ of the construct is zero, since then no subtract will be
+ generated. */
+ if (GET_MODE_CLASS (compare_mode) == MODE_FLOAT
+ && flag_trapping_math && ! is_against_zero)
+ return 0;
+
/* Eliminate half of the comparisons by switching operands, this
makes the remaining code simpler. */
if (code == UNLT || code == UNGT || code == UNORDERED || code == NE
@@ -11272,14 +11284,18 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx
|| (! rtx_equal_p (op0, true_cond)
&& ! rtx_equal_p (op1, true_cond))))
return 0;
+
/* At this point we know we can use fsel. */
/* Reduce the comparison to a comparison against zero. */
- temp = gen_reg_rtx (compare_mode);
- emit_insn (gen_rtx_SET (VOIDmode, temp,
- gen_rtx_MINUS (compare_mode, op0, op1)));
- op0 = temp;
- op1 = CONST0_RTX (compare_mode);
+ if (! is_against_zero)
+ {
+ temp = gen_reg_rtx (compare_mode);
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_MINUS (compare_mode, op0, op1)));
+ op0 = temp;
+ op1 = CONST0_RTX (compare_mode);
+ }
/* If we don't care about NaNs we can reduce some of the comparisons
down to faster ones. */
Index: testsuite/gcc.dg/ppc-fsel-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/ppc-fsel-1.c,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 ppc-fsel-1.c
--- testsuite/gcc.dg/ppc-fsel-1.c 3 May 2003 23:16:56 -0000 1.1
+++ testsuite/gcc.dg/ppc-fsel-1.c 7 Oct 2004 21:05:20 -0000
@@ -1,8 +1,8 @@
/* { dg-do compile { target powerpc*-*-* } } */
-/* { dg-options "-O -mpowerpc-gfxopt" } */
+/* { dg-options "-O -mpowerpc-gfxopt -fno-trapping-math" } */
/* { dg-final { scan-assembler "fsel" } } */
-/* Check that fsel can be generated even without -ffast-math. */
+/* If the user doesn't care about signals, fsel can be used in many cases. */
double foo(double a, double b, double c, double d)
{
Index: testsuite/gcc.dg/ppc-fsel-3.c
===================================================================
RCS file: testsuite/gcc.dg/ppc-fsel-3.c
diff -N testsuite/gcc.dg/ppc-fsel-3.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/ppc-fsel-3.c 7 Oct 2004 21:05:20 -0000
@@ -0,0 +1,11 @@
+/* { dg-do compile { target powerpc*-*-* } } */
+/* { dg-options "-O -mpowerpc-gfxopt" } */
+/* { dg-final { scan-assembler-not "fsub" } } */
+
+/* Check that an fsub isn't generated when no arithmetic was requested;
+ such an fsub might incorrectly set floating-point exception flags. */
+
+double foo(double a, double b, double c, double d)
+{
+ return a < b ? c : d;
+}
============================================================