Reorganize -ffast-math code.

Brad Lucier lucier@zakon.math.purdue.edu
Sun Mar 4 23:51:00 GMT 2001


Since Joseph Myers was kind enough to show an interest in my
suggestion of

http://gcc.gnu.org/ml/gcc-patches/2000-12/msg00690.html

I decided to reconstruct my changes for the current CVS head.

The purpose here is to separate and rationalize the various
purposes for which flag_fast_math is used in various parts of gcc.
The following patches removes flag_fast_math from toplev.c and
introduces two new flags

int flag_unsafe_math_optimizations = 0;
int flag_trapping_math = 1;

with associated options -funsafe-math-optimizations and
-fno-trapping-math.

Together with the existing

int flag_errno_math = 1;

these three flags seem to encapsulate all the different uses
that flag_fast_math fills at the moment.

The -ffast-math option still exists, it simply sets these
three flags to the opposite of their defaults; -fno-fast-math
resets them to their defaults.  These flags can be interspersed,
they are interpreted in order and can override each other.

These patches also fix an association error in fold_const.c, as
reported in optimization/2175.

I bootstrapped the compiler with --enable-languages=c,c++,f77,objc
on i686-pc-linux-gnu with and without these patches.  These patches
introduce no new warnings.  I couldn't get dejagnu installed
properly on my intel box, and right now I can't get the trunk CVS
to build on my alphaev6-unknown-linux-gnu box, so I have no
test results yet.  (The patches did apply cleanly on my alpha box
with a new CVS checkout after being generated on my intel box.)
Perhaps someone else with a working dejagnu setup and an interest
in these patches could test them.

Brad Lucier

Here are some comments and questions about the patches:

	* gcc/config/convex/convex.md: Why is flag_fast_math checked before
	generating builtins?  Do these builtins incompletely implement
	these functions for all IEEE arguments and results?  If so, then
	we should go with my change to check flag_unsafe_math_optimizations
	instead of flag_fast_math.  If this is just to make sure that
	errno is set properly, this is checked in gcc/builtins.c
	(expand_builtin_mathfn) if flag_errno_math is 1 (the default),
	so the check is not needed here.
	* gcc/config/i386/i386.md: Same questions.
	* gcc/config/m68k/m68k.md: Same questions.
	* gcc/config/mips/mips.md: Same questions.
	* gcc/gcc.c: __FAST_MATH__ does not appear anywhere in the source
	tree, and I can't see the utility of this definition.
	
The ChangeLog entry:

	* gcc/builtins.c (expand_builtin_mathfn): Generate checking code if
	flag_errno_math for builtin math functions.
	(expand_builtin): Treat sin and cos like sqrt.
	* gcc/combine.c (combine_simplify_rtx): Check 
	flag_unsafe_math_optimizations, not flag_fast_math.
	(simplify_if_then_else): Likewise.
	* gcc/config/alpha/alpha.c (alpha_emit_conditional_branch): Likewise.
	(alpha_emit_conditional_move): Initialize local_fast_math to
	flag_unsafe_math_optimizations, not flat_fast_math.
	* gcc/config/c4x/c4x.c (c4x_override_options): Call set_fast_math_flags
	instead of setting flag_fast_math to 1.
	* gcc/config/convex/convex.md: Check flag_unsafe_math_optimizations,
	not flag_fast_math.
	* gcc/config/i386/i386.c (override_options): Remove MASK_IEEE_FP
	from target_flags if flag_unsafe_math_optimizations, not if
	flag_fast_math.
	* gcc/config/i386/i386.md: Allow math function builtins to match
	if flag_unsafe_math_optimizations, not flag_fast_math.
	* gcc/config/m68k/m68k.md: Likewise.
	* gcc/config/mips/mips.md: Likewise.
	* gcc/config/rs6000/rs6000.c (validate_condition_mode): Check
	flag_unsafe_math_optimizations, not flag_fast_math.
	(rs6000_generate_compare): Likewise.
	* gcc/cse.c (fold_rtx): Likewise.
	* gcc/f/g77.texi: Document new options -funsafe-math-optimizations
	and -fno-trapping-math.  Revise documentation for -ffast-math.
	* gcc/flags.h: Remove flag_fast_math.  Add 
	flag_unsafe_math_optimizations and flag_trapping_math.
	* gcc/fold-const.c (negate_expr): Check
	flag_unsafe_math_optimizations, not flag_fast_math.
	(invert_truthvalue): Likewise.
	(fold): Likewise.  Before associating operands, check that
	code == MULT_EXPR, not code != MULT_EXPR.
	* gcc/gcc.c: Do not define __FAST_MATH__ if -ffast-math.
	* gcc/ifcvt.c (noce_try_minmax): Check
	flag_unsafe_math_optimizations, not flag_fast_math.
	(noce_operand_ok): Check flag_trapping_math, not flag_fast_math.
	* gcc/invoke.texi: Document -funsafe-math-optimizations and
	-fno-trapping-math.  Change documentation for -ffast-math.
	* gcc/java/typeck.c (convert): Check
	flag_unsafe_math_optimizations, not flag_fast_math.
	* gcc/jump.c (reversed_comparison_code_parts): Likewise.
	(rtx_equal_for_thread_p): Likewise.
	* gcc/optabs.c (emit_conditional_move): Likewise.
	* gcc/simplify-rtx.c (simplify_binary_operation): Likewise.
	(simplify_relational_operation): Likewise.
	(simplify_ternary_operation): Likewise.
	* gcc/toplev.c: Remove flag_fast_math.  Add flag_trapping_math and
	flag_unsafe_math_optimizations.  Remove fast-math entry from f_options.
	Add trapping-math and unsafe-math-optimizations entries to f_options.
	(set_fast_math_flags): New, sets flags for -ffast-math.
	(set_no_fast_math_flags): New, sets flags for -fno-fast-math.
	(decode_f_option): Add code to handle -ffast-math and -fno-fast-math.
	* gcc/toplev.h: Declare set_fast_math_flags and set_no_fast_math_flags.

And the patches themselves:

diff -p -r -x RCS gcc/gcc/builtins.c gcc-new/gcc/builtins.c
*** gcc/gcc/builtins.c	Wed Feb  7 05:24:22 2001
--- gcc-new/gcc/builtins.c	Sun Mar  4 18:06:42 2001
*************** expand_builtin_mathfn (exp, target, subt
*** 1430,1439 ****
        return 0;
      }
  
!   /* Check the results by default.  But if flag_fast_math is turned on,
!      then assume sqrt will always be called with valid arguments.  */
  
!   if (flag_errno_math && ! flag_fast_math)
      {
        rtx lab1;
  
--- 1430,1438 ----
        return 0;
      }
  
!   /* If errno must be maintained, check the result.  */
  
!   if (flag_errno_math)
      {
        rtx lab1;
  
*************** expand_builtin (exp, target, subtarget, 
*** 3329,3337 ****
  
      case BUILT_IN_SIN:
      case BUILT_IN_COS:
!       /* Treat these like sqrt, but only if the user asks for them.  */
!       if (! flag_fast_math)
! 	break;
      case BUILT_IN_FSQRT:
        target = expand_builtin_mathfn (exp, target, subtarget);
        if (target)
--- 3328,3334 ----
  
      case BUILT_IN_SIN:
      case BUILT_IN_COS:
!       /* Treat these like sqrt.  */
      case BUILT_IN_FSQRT:
        target = expand_builtin_mathfn (exp, target, subtarget);
        if (target)
diff -p -r -x RCS gcc/gcc/combine.c gcc-new/gcc/combine.c
*** gcc/gcc/combine.c	Fri Mar  2 23:19:50 2001
--- gcc-new/gcc/combine.c	Sun Mar  4 18:09:59 2001
*************** combine_simplify_rtx (x, op0_mode, last,
*** 4021,4027 ****
  	  && (! FLOAT_MODE_P (mode)
  	      /* x-y != -(y-x) with IEEE floating point.  */
  	      || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	      || flag_fast_math))
  	return gen_binary (MINUS, mode, XEXP (XEXP (x, 0), 1),
  			   XEXP (XEXP (x, 0), 0));
  
--- 4021,4027 ----
  	  && (! FLOAT_MODE_P (mode)
  	      /* x-y != -(y-x) with IEEE floating point.  */
  	      || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	      || flag_unsafe_math_optimizations))
  	return gen_binary (MINUS, mode, XEXP (XEXP (x, 0), 1),
  			   XEXP (XEXP (x, 0), 0));
  
*************** combine_simplify_rtx (x, op0_mode, last,
*** 4189,4195 ****
        /* In IEEE floating point, x-0 is not the same as x.  */
        if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
  	   || ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0)))
! 	   || flag_fast_math)
  	  && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
  	return XEXP (x, 0);
        break;
--- 4189,4195 ----
        /* In IEEE floating point, x-0 is not the same as x.  */
        if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
  	   || ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0)))
! 	   || flag_unsafe_math_optimizations)
  	  && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
  	return XEXP (x, 0);
        break;
*************** simplify_if_then_else (x)
*** 4777,4788 ****
  
    /* Convert a == b ? b : a to "a".  */
    if (true_code == EQ && ! side_effects_p (cond)
!       && (! FLOAT_MODE_P (mode) || flag_fast_math)
        && rtx_equal_p (XEXP (cond, 0), false_rtx)
        && rtx_equal_p (XEXP (cond, 1), true_rtx))
      return false_rtx;
    else if (true_code == NE && ! side_effects_p (cond)
! 	   && (! FLOAT_MODE_P (mode) || flag_fast_math)
  	   && rtx_equal_p (XEXP (cond, 0), true_rtx)
  	   && rtx_equal_p (XEXP (cond, 1), false_rtx))
      return true_rtx;
--- 4777,4788 ----
  
    /* Convert a == b ? b : a to "a".  */
    if (true_code == EQ && ! side_effects_p (cond)
!       && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
        && rtx_equal_p (XEXP (cond, 0), false_rtx)
        && rtx_equal_p (XEXP (cond, 1), true_rtx))
      return false_rtx;
    else if (true_code == NE && ! side_effects_p (cond)
! 	   && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
  	   && rtx_equal_p (XEXP (cond, 0), true_rtx)
  	   && rtx_equal_p (XEXP (cond, 1), false_rtx))
      return true_rtx;
*************** simplify_if_then_else (x)
*** 4810,4816 ****
  
    /* Look for MIN or MAX.  */
  
!   if ((! FLOAT_MODE_P (mode) || flag_fast_math)
        && comparison_p
        && rtx_equal_p (XEXP (cond, 0), true_rtx)
        && rtx_equal_p (XEXP (cond, 1), false_rtx)
--- 4810,4816 ----
  
    /* Look for MIN or MAX.  */
  
!   if ((! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
        && comparison_p
        && rtx_equal_p (XEXP (cond, 0), true_rtx)
        && rtx_equal_p (XEXP (cond, 1), false_rtx)
diff -p -r -x RCS gcc/gcc/config/alpha/alpha.c gcc-new/gcc/config/alpha/alpha.c
*** gcc/gcc/config/alpha/alpha.c	Tue Jan 16 09:29:08 2001
--- gcc-new/gcc/config/alpha/alpha.c	Sun Mar  4 20:09:59 2001
*************** alpha_emit_conditional_branch (code)
*** 1678,1684 ****
    if (alpha_compare.fp_p)
      {
        cmp_mode = DFmode;
!       if (flag_fast_math)
  	{
  	  /* When we are not as concerned about non-finite values, and we
  	     are comparing against zero, we can branch directly.  */
--- 1678,1684 ----
    if (alpha_compare.fp_p)
      {
        cmp_mode = DFmode;
!       if (flag_unsafe_math_optimizations)
  	{
  	  /* When we are not as concerned about non-finite values, and we
  	     are comparing against zero, we can branch directly.  */
*************** alpha_emit_conditional_move (cmp, mode)
*** 1879,1885 ****
      = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0));
    enum machine_mode cmp_op_mode = fp_p ? DFmode : DImode;
    enum machine_mode cmov_mode = VOIDmode;
!   int local_fast_math = flag_fast_math;
    rtx tem;
  
    /* Zero the operands.  */
--- 1879,1885 ----
      = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0));
    enum machine_mode cmp_op_mode = fp_p ? DFmode : DImode;
    enum machine_mode cmov_mode = VOIDmode;
!   int local_fast_math = flag_unsafe_math_optimizations;
    rtx tem;
  
    /* Zero the operands.  */
diff -p -r -x RCS gcc/gcc/config/c4x/c4x.c gcc-new/gcc/config/c4x/c4x.c
*** gcc/gcc/config/c4x/c4x.c	Sun Feb  4 17:44:11 2001
--- gcc-new/gcc/config/c4x/c4x.c	Sun Mar  4 20:28:50 2001
*************** c4x_override_options ()
*** 278,284 ****
      target_flags &= ~C3X_FLAG;
  
    /* Convert foo / 8.0 into foo * 0.125, etc.  */
!   flag_fast_math = 1;
  
    /* We should phase out the following at some stage.
       This provides compatibility with the old -mno-aliases option.  */
--- 278,284 ----
      target_flags &= ~C3X_FLAG;
  
    /* Convert foo / 8.0 into foo * 0.125, etc.  */
!   set_fast_math_flags();
  
    /* We should phase out the following at some stage.
       This provides compatibility with the old -mno-aliases option.  */
diff -p -r -x RCS gcc/gcc/config/convex/convex.md gcc-new/gcc/config/convex/convex.md
*** gcc/gcc/config/convex/convex.md	Tue Sep 12 09:58:46 2000
--- gcc-new/gcc/config/convex/convex.md	Sun Mar  4 20:33:28 2001
***************
*** 1309,1347 ****
  (define_insn "sqrtdf2"
    [(set (match_operand:DF 0 "register_operand" "=d")
  	(sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
!   "! TARGET_C1 && flag_fast_math"
    "sqrt.d %0"
    [(set_attr "type" "divd")])
  
  (define_insn "sqrtsf2"
    [(set (match_operand:SF 0 "register_operand" "=d")
  	(sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
!   "! TARGET_C1 && flag_fast_math"
    "sqrt.s %0"
    [(set_attr "type" "divs")])
  
  (define_insn "sindf2"
    [(set (match_operand:DF 0 "register_operand" "=d")
  	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
!   "! TARGET_C1 && flag_fast_math"
    "sin.d %0")
  
  (define_insn "sinsf2"
    [(set (match_operand:SF 0 "register_operand" "=d")
  	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
!   "! TARGET_C1 && flag_fast_math"
    "sin.s %0")
  
  (define_insn "cosdf2"
    [(set (match_operand:DF 0 "register_operand" "=d")
  	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
!   "! TARGET_C1 && flag_fast_math"
    "cos.d %0")
  
  (define_insn "cossf2"
    [(set (match_operand:SF 0 "register_operand" "=d")
  	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
!   "! TARGET_C1 && flag_fast_math"
    "cos.s %0")
  
  (define_insn "ftruncdf2"
--- 1309,1347 ----
  (define_insn "sqrtdf2"
    [(set (match_operand:DF 0 "register_operand" "=d")
  	(sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
!   "! TARGET_C1 && flag_unsafe_math_optimizations"
    "sqrt.d %0"
    [(set_attr "type" "divd")])
  
  (define_insn "sqrtsf2"
    [(set (match_operand:SF 0 "register_operand" "=d")
  	(sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
!   "! TARGET_C1 && flag_unsafe_math_optimizations"
    "sqrt.s %0"
    [(set_attr "type" "divs")])
  
  (define_insn "sindf2"
    [(set (match_operand:DF 0 "register_operand" "=d")
  	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
!   "! TARGET_C1 && flag_unsafe_math_optimizations"
    "sin.d %0")
  
  (define_insn "sinsf2"
    [(set (match_operand:SF 0 "register_operand" "=d")
  	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
!   "! TARGET_C1 && flag_unsafe_math_optimizations"
    "sin.s %0")
  
  (define_insn "cosdf2"
    [(set (match_operand:DF 0 "register_operand" "=d")
  	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
!   "! TARGET_C1 && flag_unsafe_math_optimizations"
    "cos.d %0")
  
  (define_insn "cossf2"
    [(set (match_operand:SF 0 "register_operand" "=d")
  	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
!   "! TARGET_C1 && flag_unsafe_math_optimizations"
    "cos.s %0")
  
  (define_insn "ftruncdf2"
diff -p -r -x RCS gcc/gcc/config/i386/i386.c gcc-new/gcc/config/i386/i386.c
*** gcc/gcc/config/i386/i386.c	Sat Mar  3 13:49:04 2001
--- gcc-new/gcc/config/i386/i386.c	Sun Mar  4 20:35:18 2001
*************** override_options ()
*** 748,754 ****
  
    /* If we're doing fast math, we don't care about comparison order
       wrt NaNs.  This lets us use a shorter comparison sequence.  */
!   if (flag_fast_math)
      target_flags &= ~MASK_IEEE_FP;
  
    /* It makes no sense to ask for just SSE builtins, so MMX is also turned
--- 748,754 ----
  
    /* If we're doing fast math, we don't care about comparison order
       wrt NaNs.  This lets us use a shorter comparison sequence.  */
!   if (flag_unsafe_math_optimizations)
      target_flags &= ~MASK_IEEE_FP;
  
    /* It makes no sense to ask for just SSE builtins, so MMX is also turned
diff -p -r -x RCS gcc/gcc/config/i386/i386.md gcc-new/gcc/config/i386/i386.md
*** gcc/gcc/config/i386/i386.md	Sat Mar  3 13:49:05 2001
--- gcc-new/gcc/config/i386/i386.md	Sun Mar  4 20:38:13 2001
***************
*** 10991,10997 ****
    [(set (match_operand:XF 0 "register_operand" "=f")
  	(sqrt:XF (match_operand:XF 1 "register_operand" "0")))]
    "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
!    && (TARGET_IEEE_FP || flag_fast_math) "
    "fsqrt"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")
--- 10991,10997 ----
    [(set (match_operand:XF 0 "register_operand" "=f")
  	(sqrt:XF (match_operand:XF 1 "register_operand" "0")))]
    "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
!    && (TARGET_IEEE_FP || flag_unsafe_math_optimizations) "
    "fsqrt"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")
***************
*** 11001,11007 ****
    [(set (match_operand:TF 0 "register_operand" "=f")
  	(sqrt:TF (match_operand:TF 1 "register_operand" "0")))]
    "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
!    && (TARGET_IEEE_FP || flag_fast_math) "
    "fsqrt"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")
--- 11001,11007 ----
    [(set (match_operand:TF 0 "register_operand" "=f")
  	(sqrt:TF (match_operand:TF 1 "register_operand" "0")))]
    "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
!    && (TARGET_IEEE_FP || flag_unsafe_math_optimizations) "
    "fsqrt"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")
***************
*** 11050,11056 ****
  (define_insn "sindf2"
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
    "fsin"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "DF")])
--- 11050,11056 ----
  (define_insn "sindf2"
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations"
    "fsin"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "DF")])
***************
*** 11058,11064 ****
  (define_insn "sinsf2"
    [(set (match_operand:SF 0 "register_operand" "=f")
  	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
    "fsin"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "SF")])
--- 11058,11064 ----
  (define_insn "sinsf2"
    [(set (match_operand:SF 0 "register_operand" "=f")
  	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations"
    "fsin"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "SF")])
***************
*** 11067,11073 ****
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(unspec:DF [(float_extend:DF
  		     (match_operand:SF 1 "register_operand" "0"))] 1))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
    "fsin"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "DF")])
--- 11067,11073 ----
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(unspec:DF [(float_extend:DF
  		     (match_operand:SF 1 "register_operand" "0"))] 1))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations"
    "fsin"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "DF")])
***************
*** 11075,11081 ****
  (define_insn "sinxf2"
    [(set (match_operand:XF 0 "register_operand" "=f")
  	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
    "fsin"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")])
--- 11075,11081 ----
  (define_insn "sinxf2"
    [(set (match_operand:XF 0 "register_operand" "=f")
  	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations"
    "fsin"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")])
***************
*** 11083,11089 ****
  (define_insn "sintf2"
    [(set (match_operand:TF 0 "register_operand" "=f")
  	(unspec:TF [(match_operand:TF 1 "register_operand" "0")] 1))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
    "fsin"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")])
--- 11083,11089 ----
  (define_insn "sintf2"
    [(set (match_operand:TF 0 "register_operand" "=f")
  	(unspec:TF [(match_operand:TF 1 "register_operand" "0")] 1))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations"
    "fsin"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")])
***************
*** 11091,11097 ****
  (define_insn "cosdf2"
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
    "fcos"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "DF")])
--- 11091,11097 ----
  (define_insn "cosdf2"
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations"
    "fcos"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "DF")])
***************
*** 11099,11105 ****
  (define_insn "cossf2"
    [(set (match_operand:SF 0 "register_operand" "=f")
  	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
    "fcos"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "SF")])
--- 11099,11105 ----
  (define_insn "cossf2"
    [(set (match_operand:SF 0 "register_operand" "=f")
  	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations"
    "fcos"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "SF")])
***************
*** 11108,11114 ****
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(unspec:DF [(float_extend:DF
  		     (match_operand:SF 1 "register_operand" "0"))] 2))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
    "fcos"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "DF")])
--- 11108,11114 ----
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(unspec:DF [(float_extend:DF
  		     (match_operand:SF 1 "register_operand" "0"))] 2))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations"
    "fcos"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "DF")])
***************
*** 11116,11122 ****
  (define_insn "cosxf2"
    [(set (match_operand:XF 0 "register_operand" "=f")
  	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
    "fcos"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")])
--- 11116,11122 ----
  (define_insn "cosxf2"
    [(set (match_operand:XF 0 "register_operand" "=f")
  	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations"
    "fcos"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")])
***************
*** 11124,11130 ****
  (define_insn "costf2"
    [(set (match_operand:TF 0 "register_operand" "=f")
  	(unspec:TF [(match_operand:TF 1 "register_operand" "0")] 2))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
    "fcos"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")])
--- 11124,11130 ----
  (define_insn "costf2"
    [(set (match_operand:TF 0 "register_operand" "=f")
  	(unspec:TF [(match_operand:TF 1 "register_operand" "0")] 2))]
!   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations"
    "fcos"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")])
diff -p -r -x RCS gcc/gcc/config/m68k/m68k.md gcc-new/gcc/config/m68k/m68k.md
*** gcc/gcc/config/m68k/m68k.md	Tue Nov 28 16:31:43 2000
--- gcc-new/gcc/config/m68k/m68k.md	Sun Mar  4 20:40:13 2001
***************
*** 7840,7846 ****
  (define_insn "sinsf2"
    [(set (match_operand:SF 0 "general_operand" "=f")
  	(unspec:SF [(match_operand:SF 1 "general_operand" "fm")] 1))]
!   "TARGET_68881 && flag_fast_math"
    "*
  {
    if (FP_REG_P (operands[1]))
--- 7840,7846 ----
  (define_insn "sinsf2"
    [(set (match_operand:SF 0 "general_operand" "=f")
  	(unspec:SF [(match_operand:SF 1 "general_operand" "fm")] 1))]
!   "TARGET_68881 && flag_unsafe_math_optimizations"
    "*
  {
    if (FP_REG_P (operands[1]))
***************
*** 7852,7858 ****
  (define_insn "sindf2"
    [(set (match_operand:DF 0 "general_operand" "=f")
  	(unspec:DF [(match_operand:DF 1 "general_operand" "fm")] 1))]
!   "TARGET_68881 && flag_fast_math"
    "*
  {
    if (FP_REG_P (operands[1]))
--- 7852,7858 ----
  (define_insn "sindf2"
    [(set (match_operand:DF 0 "general_operand" "=f")
  	(unspec:DF [(match_operand:DF 1 "general_operand" "fm")] 1))]
!   "TARGET_68881 && flag_unsafe_math_optimizations"
    "*
  {
    if (FP_REG_P (operands[1]))
***************
*** 7864,7876 ****
  (define_insn "sinxf2"
    [(set (match_operand:XF 0 "general_operand" "=f")
  	(unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 1))]
!   "TARGET_68881 && flag_fast_math"
    "fsin%.x %1,%0")
  
  (define_insn "cossf2"
    [(set (match_operand:SF 0 "general_operand" "=f")
  	(unspec:SF [(match_operand:SF 1 "general_operand" "fm")] 2))]
!   "TARGET_68881 && flag_fast_math"
    "*
  {
    if (FP_REG_P (operands[1]))
--- 7864,7876 ----
  (define_insn "sinxf2"
    [(set (match_operand:XF 0 "general_operand" "=f")
  	(unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 1))]
!   "TARGET_68881 && flag_unsafe_math_optimizations"
    "fsin%.x %1,%0")
  
  (define_insn "cossf2"
    [(set (match_operand:SF 0 "general_operand" "=f")
  	(unspec:SF [(match_operand:SF 1 "general_operand" "fm")] 2))]
!   "TARGET_68881 && flag_unsafe_math_optimizations"
    "*
  {
    if (FP_REG_P (operands[1]))
***************
*** 7882,7888 ****
  (define_insn "cosdf2"
    [(set (match_operand:DF 0 "general_operand" "=f")
  	(unspec:DF [(match_operand:DF 1 "general_operand" "fm")] 2))]
!   "TARGET_68881 && flag_fast_math"
    "*
  {
    if (FP_REG_P (operands[1]))
--- 7882,7888 ----
  (define_insn "cosdf2"
    [(set (match_operand:DF 0 "general_operand" "=f")
  	(unspec:DF [(match_operand:DF 1 "general_operand" "fm")] 2))]
!   "TARGET_68881 && flag_unsafe_math_optimizations"
    "*
  {
    if (FP_REG_P (operands[1]))
***************
*** 7894,7900 ****
  (define_insn "cosxf2"
    [(set (match_operand:XF 0 "general_operand" "=f")
  	(unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 2))]
!   "TARGET_68881 && flag_fast_math"
    "fcos%.x %1,%0")
  
  (define_insn "trap"
--- 7894,7900 ----
  (define_insn "cosxf2"
    [(set (match_operand:XF 0 "general_operand" "=f")
  	(unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 2))]
!   "TARGET_68881 && flag_unsafe_math_optimizations"
    "fcos%.x %1,%0")
  
  (define_insn "trap"
diff -p -r -x RCS gcc/gcc/config/mips/mips.md gcc-new/gcc/config/mips/mips.md
*** gcc/gcc/config/mips/mips.md	Tue Nov 28 16:31:44 2000
--- gcc-new/gcc/config/mips/mips.md	Sun Mar  4 20:42:18 2001
***************
*** 2223,2229 ****
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(div:DF (match_operand:DF 1 "const_float_1_operand" "")
  		(match_operand:DF 2 "register_operand" "f")))]
!   "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_fast_math"
    "recip.d\\t%0,%2"
    [(set_attr "type"	"fdiv")
     (set_attr "mode"	"DF")])
--- 2223,2229 ----
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(div:DF (match_operand:DF 1 "const_float_1_operand" "")
  		(match_operand:DF 2 "register_operand" "f")))]
!   "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations"
    "recip.d\\t%0,%2"
    [(set_attr "type"	"fdiv")
     (set_attr "mode"	"DF")])
***************
*** 2232,2238 ****
    [(set (match_operand:SF 0 "register_operand" "=f")
  	(div:SF (match_operand:SF 1 "const_float_1_operand" "")
  		(match_operand:SF 2 "register_operand" "f")))]
!   "ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_fast_math"
    "recip.s\\t%0,%2"
    [(set_attr "type"	"fdiv")
     (set_attr "mode"	"SF")])
--- 2232,2238 ----
    [(set (match_operand:SF 0 "register_operand" "=f")
  	(div:SF (match_operand:SF 1 "const_float_1_operand" "")
  		(match_operand:SF 2 "register_operand" "f")))]
!   "ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations"
    "recip.s\\t%0,%2"
    [(set_attr "type"	"fdiv")
     (set_attr "mode"	"SF")])
***************
*** 2824,2830 ****
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(div:DF (match_operand:DF 1 "const_float_1_operand" "")
  		(sqrt:DF (match_operand:DF 2 "register_operand" "f"))))]
!   "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_fast_math"
    "rsqrt.d\\t%0,%2"
    [(set_attr "type"	"fsqrt")
     (set_attr "mode"	"DF")])
--- 2824,2830 ----
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(div:DF (match_operand:DF 1 "const_float_1_operand" "")
  		(sqrt:DF (match_operand:DF 2 "register_operand" "f"))))]
!   "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations"
    "rsqrt.d\\t%0,%2"
    [(set_attr "type"	"fsqrt")
     (set_attr "mode"	"DF")])
***************
*** 2833,2839 ****
    [(set (match_operand:SF 0 "register_operand" "=f")
  	(div:SF (match_operand:SF 1 "const_float_1_operand" "")
  		(sqrt:SF (match_operand:SF 2 "register_operand" "f"))))]
!   "ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_fast_math"
    "rsqrt.s\\t%0,%2"
    [(set_attr "type"	"fsqrt")
     (set_attr "mode"	"SF")])
--- 2833,2839 ----
    [(set (match_operand:SF 0 "register_operand" "=f")
  	(div:SF (match_operand:SF 1 "const_float_1_operand" "")
  		(sqrt:SF (match_operand:SF 2 "register_operand" "f"))))]
!   "ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations"
    "rsqrt.s\\t%0,%2"
    [(set_attr "type"	"fsqrt")
     (set_attr "mode"	"SF")])
diff -p -r -x RCS gcc/gcc/config/rs6000/rs6000.c gcc-new/gcc/config/rs6000/rs6000.c
*** gcc/gcc/config/rs6000/rs6000.c	Tue Feb 20 20:50:36 2001
--- gcc-new/gcc/config/rs6000/rs6000.c	Sun Mar  4 20:48:21 2001
*************** validate_condition_mode (code, mode)
*** 3238,3246 ****
  	  || code == UNGE || code == UNLE))
      abort();
    
!   /* These should never be generated except for fast_math.  */
    if (mode == CCFPmode
!       && ! flag_fast_math
        && (code == LE || code == GE
  	  || code == UNEQ || code == LTGT
  	  || code == UNGT || code == UNLT))
--- 3238,3247 ----
  	  || code == UNGE || code == UNLE))
      abort();
    
!   /* These should never be generated except for 
!      flag_unsafe_math_optimizations.  */
    if (mode == CCFPmode
!       && ! flag_unsafe_math_optimizations
        && (code == LE || code == GE
  	  || code == UNEQ || code == LTGT
  	  || code == UNGT || code == UNLT))
*************** rs6000_generate_compare (code)
*** 4454,4462 ****
  					   rs6000_compare_op1)));
    
    /* Some kinds of FP comparisons need an OR operation;
!      except that for fast_math we don't bother.  */
    if (rs6000_compare_fp_p
!       && ! flag_fast_math
        && (code == LE || code == GE
  	  || code == UNEQ || code == LTGT
  	  || code == UNGT || code == UNLT))
--- 4455,4463 ----
  					   rs6000_compare_op1)));
    
    /* Some kinds of FP comparisons need an OR operation;
!      except for flag_unsafe_math_optimizations we don't bother.  */
    if (rs6000_compare_fp_p
!       && ! flag_unsafe_math_optimizations
        && (code == LE || code == GE
  	  || code == UNEQ || code == LTGT
  	  || code == UNGT || code == UNLT))
diff -p -r -x RCS gcc/gcc/cse.c gcc-new/gcc/cse.c
*** gcc/gcc/cse.c	Thu Mar  1 20:50:47 2001
--- gcc-new/gcc/cse.c	Sun Mar  4 18:11:48 2001
*************** fold_rtx (x, insn)
*** 3977,3983 ****
  		{
  		   /* Sadly two equal NaNs are not equivalent.  */
  		   if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 		       || ! FLOAT_MODE_P (mode_arg0) || flag_fast_math)
  		      return ((code == EQ || code == LE || code == GE
  			       || code == LEU || code == GEU || code == UNEQ
  			       || code == UNLE || code == UNGE || code == ORDERED)
--- 3977,3984 ----
  		{
  		   /* Sadly two equal NaNs are not equivalent.  */
  		   if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 		       || ! FLOAT_MODE_P (mode_arg0) 
! 		       || flag_unsafe_math_optimizations)
  		      return ((code == EQ || code == LE || code == GE
  			       || code == LEU || code == GEU || code == UNEQ
  			       || code == UNLE || code == UNGE || code == ORDERED)
diff -p -r -x RCS gcc/gcc/f/g77.texi gcc-new/gcc/f/g77.texi
*** gcc/gcc/f/g77.texi	Fri Jan  5 14:12:20 2001
--- gcc-new/gcc/f/g77.texi	Sun Mar  4 21:34:00 2001
*************** by type.  Explanations are in the follow
*** 1446,1451 ****
--- 1446,1452 ----
  -malign-double
  -ffloat-store  -fforce-mem  -fforce-addr  -fno-inline
  -ffast-math  -fstrength-reduce  -frerun-cse-after-loop
+ -funsafe-math-optimizations -fno-trapping-math
  -fexpensive-optimizations  -fdelayed-branch
  -fschedule-insns  -fschedule-insn2  -fcaller-saves
  -funroll-loops  -funroll-all-loops
*************** Note that if you are not optimizing, no 
*** 2779,2784 ****
--- 2780,2801 ----
  @cindex conformance, IEEE 754
  Might allow some programs designed to not be too dependent
  on IEEE behavior for floating-point to run faster, or die trying.
+ Sets @samp{-funsafe-math-optimizations}, and
+ @samp{-fno-trapping-math}.
+ 
+ @cindex -funsafe-math-optimizations option
+ @cindex options, -funsafe-math-optimizations
+ @item -funsafe-math-optimizations
+ Allow optimizations that may be give incorrect results
+ for certain IEEE inputs.
+ 
+ @cindex -fno-trapping-math option
+ @cindex options, -fno-trapping-math
+ @item -fno-trapping-math
+ Allow the compiler to assume that floating-point arithmetic
+ will not generate traps on any inputs.  This is useful, for
+ example, when running a program using IEEE "non-stop"
+ floating-point arithmetic.
  
  @cindex -fstrength-reduce option
  @cindex options, -fstrength-reduce
diff -p -r -x RCS gcc/gcc/flags.h gcc-new/gcc/flags.h
*** gcc/gcc/flags.h	Wed Feb 14 11:24:45 2001
--- gcc-new/gcc/flags.h	Sun Mar  4 18:13:58 2001
*************** extern int flag_volatile_global;
*** 327,347 ****
  
  extern int flag_volatile_static;
  
- /* Nonzero allows GCC to violate some IEEE or ANSI rules regarding math
-    operations in the interest of optimization.  For example it allows
-    GCC to assume arguments to sqrt are nonnegative numbers, allowing
-    faster code for sqrt to be generated. */
- 
- extern int flag_fast_math;
- 
  /* Nonzero allows GCC to optimize sibling and tail recursive calls.  */
  
  extern int flag_optimize_sibling_calls;
  
  /* Nonzero means the front end generally wants `errno' maintained by math
!    operations, like built-in SQRT, unless overridden by flag_fast_math.  */
  
  extern int flag_errno_math;
  
  /* 0 means straightforward implementation of complex divide acceptable.
     1 means wide ranges of inputs must work for complex divide.
--- 327,353 ----
  
  extern int flag_volatile_static;
  
  /* Nonzero allows GCC to optimize sibling and tail recursive calls.  */
  
  extern int flag_optimize_sibling_calls;
  
  /* Nonzero means the front end generally wants `errno' maintained by math
!    operations, like built-in SQRT.  */
  
  extern int flag_errno_math;
+ 
+ /* Nonzero means that unsafe floating-point math optimizations are allowed
+    for the sake of speed.  IEEE compliance is not guaranteed, and operations
+    are allowed to assume that their arguments and results are "normal"
+    (e.g., nonnegative for SQRT).  */
+ 
+ extern int flag_unsafe_math_optimizations;
+ 
+ /* Zero means that floating-point math operations cannot generate a
+    (user-visible) trap.  This is the case, for example, in nonstop
+    IEEE 754 arithmetic.  */
+ 
+ extern int flag_trapping_math;
  
  /* 0 means straightforward implementation of complex divide acceptable.
     1 means wide ranges of inputs must work for complex divide.
diff -p -r -x RCS gcc/gcc/fold-const.c gcc-new/gcc/fold-const.c
*** gcc/gcc/fold-const.c	Thu Mar  1 20:50:49 2001
--- gcc-new/gcc/fold-const.c	Sun Mar  4 18:34:58 2001
*************** negate_expr (t)
*** 1311,1317 ****
  
      case MINUS_EXPR:
        /* - (A - B) -> B - A  */
!       if (! FLOAT_TYPE_P (type) || flag_fast_math)
  	return convert (type,
  			fold (build (MINUS_EXPR, TREE_TYPE (t),
  				     TREE_OPERAND (t, 1),
--- 1311,1317 ----
  
      case MINUS_EXPR:
        /* - (A - B) -> B - A  */
!       if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
  	return convert (type,
  			fold (build (MINUS_EXPR, TREE_TYPE (t),
  				     TREE_OPERAND (t, 1),
*************** invert_truthvalue (arg)
*** 2719,2725 ****
    if (TREE_CODE_CLASS (code) == '<')
      {
        if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
! 	  && !flag_fast_math && code != NE_EXPR && code != EQ_EXPR)
  	return build1 (TRUTH_NOT_EXPR, type, arg);
        else
  	return build (invert_tree_comparison (code), type,
--- 2719,2727 ----
    if (TREE_CODE_CLASS (code) == '<')
      {
        if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
! 	  && !flag_unsafe_math_optimizations
! 	  && code != NE_EXPR 
! 	  && code != EQ_EXPR)
  	return build1 (TRUTH_NOT_EXPR, type, arg);
        else
  	return build (invert_tree_comparison (code), type,
*************** fold (expr)
*** 5262,5268 ****
  
        /* Convert - (a - b) to (b - a) for non-floating-point.  */
        else if (TREE_CODE (arg0) == MINUS_EXPR
! 	       && (! FLOAT_TYPE_P (type) || flag_fast_math))
  	return build (MINUS_EXPR, type, TREE_OPERAND (arg0, 1),
  		      TREE_OPERAND (arg0, 0));
  
--- 5264,5270 ----
  
        /* Convert - (a - b) to (b - a) for non-floating-point.  */
        else if (TREE_CODE (arg0) == MINUS_EXPR
! 	       && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
  	return build (MINUS_EXPR, type, TREE_OPERAND (arg0, 1),
  		      TREE_OPERAND (arg0, 0));
  
*************** fold (expr)
*** 5457,5463 ****
  	}
        /* In IEEE floating point, x+0 may not equal x.  */
        else if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 		|| flag_fast_math)
  	       && real_zerop (arg1))
  	return non_lvalue (convert (type, arg0));
        /* x+(-0) equals x, even for IEEE.  */
--- 5459,5465 ----
  	}
        /* In IEEE floating point, x+0 may not equal x.  */
        else if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 		|| flag_unsafe_math_optimizations)
  	       && real_zerop (arg1))
  	return non_lvalue (convert (type, arg0));
        /* x+(-0) equals x, even for IEEE.  */
*************** fold (expr)
*** 5541,5551 ****
  	 parentheses.  Rather than remember where the parentheses were, we
  	 don't associate floats at all.  It shouldn't matter much.  However,
  	 associating multiplications is only very slightly inaccurate, so do
! 	 that if -ffast-math is specified.  */
  
        if (! wins
  	  && (! FLOAT_TYPE_P (type)
! 	      || (flag_fast_math && code != MULT_EXPR)))
  	{
  	  tree var0, con0, lit0, var1, con1, lit1;
  
--- 5543,5553 ----
  	 parentheses.  Rather than remember where the parentheses were, we
  	 don't associate floats at all.  It shouldn't matter much.  However,
  	 associating multiplications is only very slightly inaccurate, so do
! 	 that if -funsafe-math-optimizations is specified.  */
  
        if (! wins
  	  && (! FLOAT_TYPE_P (type)
! 	      || (flag_unsafe_math_optimizations && code == MULT_EXPR)))
  	{
  	  tree var0, con0, lit0, var1, con1, lit1;
  
*************** fold (expr)
*** 5622,5628 ****
  	}
  
        else if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	       || flag_fast_math)
  	{
  	  /* Except with IEEE floating point, 0-x equals -x.  */
  	  if (! wins && real_zerop (arg0))
--- 5624,5630 ----
  	}
  
        else if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	       || flag_unsafe_math_optimizations)
  	{
  	  /* Except with IEEE floating point, 0-x equals -x.  */
  	  if (! wins && real_zerop (arg0))
*************** fold (expr)
*** 5638,5644 ****
  	 Also note that operand_equal_p is always false if an operand
  	 is volatile.  */
  
!       if ((! FLOAT_TYPE_P (type) || flag_fast_math)
  	  && operand_equal_p (arg0, arg1, 0))
  	return convert (type, integer_zero_node);
  
--- 5640,5646 ----
  	 Also note that operand_equal_p is always false if an operand
  	 is volatile.  */
  
!       if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
  	  && operand_equal_p (arg0, arg1, 0))
  	return convert (type, integer_zero_node);
  
*************** fold (expr)
*** 5677,5683 ****
  	{
  	  /* x*0 is 0, except for IEEE floating point.  */
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	       || flag_fast_math)
  	      && real_zerop (arg1))
  	    return omit_one_operand (type, arg1, arg0);
  	  /* In IEEE floating point, x*1 is not equivalent to x for snans.
--- 5679,5685 ----
  	{
  	  /* x*0 is 0, except for IEEE floating point.  */
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	       || flag_unsafe_math_optimizations)
  	      && real_zerop (arg1))
  	    return omit_one_operand (type, arg1, arg0);
  	  /* In IEEE floating point, x*1 is not equivalent to x for snans.
*************** fold (expr)
*** 5834,5845 ****
  
        /* If ARG1 is a constant, we can convert this to a multiply by the
  	 reciprocal.  This does not have the same rounding properties,
! 	 so only do this if -ffast-math.  We can actually always safely
! 	 do it if ARG1 is a power of two, but it's hard to tell if it is
! 	 or not in a portable manner.  */
        if (TREE_CODE (arg1) == REAL_CST)
  	{
! 	  if (flag_fast_math
  	      && 0 != (tem = const_binop (code, build_real (type, dconst1),
  					  arg1, 0)))
  	    return fold (build (MULT_EXPR, type, arg0, tem));
--- 5836,5847 ----
  
        /* If ARG1 is a constant, we can convert this to a multiply by the
  	 reciprocal.  This does not have the same rounding properties,
! 	 so only do this if -funsafe-math-optimizations.  We can actually
! 	 always safely do it if ARG1 is a power of two, but it's hard to
! 	 tell if it is or not in a portable manner.  */
        if (TREE_CODE (arg1) == REAL_CST)
  	{
! 	  if (flag_unsafe_math_optimizations
  	      && 0 != (tem = const_binop (code, build_real (type, dconst1),
  					  arg1, 0)))
  	    return fold (build (MULT_EXPR, type, arg0, tem));
*************** fold (expr)
*** 6899,6905 ****
        if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
  	  && (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
  	      || ! FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0)))
! 	      || flag_fast_math)
  	  && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
  					     arg1, TREE_OPERAND (arg0, 1)))
  	{
--- 6901,6907 ----
        if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
  	  && (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
  	      || ! FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0)))
! 	      || flag_unsafe_math_optimizations)
  	  && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
  					     arg1, TREE_OPERAND (arg0, 1)))
  	{
diff -p -r -x RCS gcc/gcc/gcc.c gcc-new/gcc/gcc.c
*** gcc/gcc/gcc.c	Sun Mar  4 04:08:17 2001
--- gcc-new/gcc/gcc.c	Sun Mar  4 21:08:33 2001
*************** static const char *cpp_options =
*** 636,642 ****
   %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
   %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
   %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
-  %{ffast-math:-D__FAST_MATH__}\
   %{fshort-wchar:-U__WCHAR_TYPE__ -D__WCHAR_TYPE__=short\\ unsigned\\ int}\
   %{ffreestanding:-D__STDC_HOSTED__=0} %{fno-hosted:-D__STDC_HOSTED__=0}\
   %{!ffreestanding:%{!fno-hosted:-D__STDC_HOSTED__=1}}\
--- 636,641 ----
diff -p -r -x RCS gcc/gcc/ifcvt.c gcc-new/gcc/ifcvt.c
*** gcc/gcc/ifcvt.c	Fri Mar  2 06:00:29 2001
--- gcc-new/gcc/ifcvt.c	Sun Mar  4 19:26:31 2001
*************** noce_try_minmax (if_info)
*** 1143,1149 ****
       to get the target to tell us...  */
    if (FLOAT_MODE_P (GET_MODE (if_info->x))
        && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
!       && ! flag_fast_math)
      return FALSE;
  
    cond = noce_get_alt_condition (if_info, if_info->a, &earliest);
--- 1143,1149 ----
       to get the target to tell us...  */
    if (FLOAT_MODE_P (GET_MODE (if_info->x))
        && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
!       && ! flag_unsafe_math_optimizations)
      return FALSE;
  
    cond = noce_get_alt_condition (if_info, if_info->a, &earliest);
*************** noce_operand_ok (op)
*** 1397,1406 ****
    if (side_effects_p (op))
      return FALSE;
  
!   /* ??? Unfortuantely may_trap_p can't look at flag_fast_math, due to
       being linked into the genfoo programs.  This is probably a mistake.
       With finite operands, most fp operations don't trap.  */
!   if (flag_fast_math && FLOAT_MODE_P (GET_MODE (op)))
      switch (GET_CODE (op))
        {
        case DIV:
--- 1397,1406 ----
    if (side_effects_p (op))
      return FALSE;
  
!   /* ??? Unfortuantely may_trap_p can't look at flag_trapping_math, due to
       being linked into the genfoo programs.  This is probably a mistake.
       With finite operands, most fp operations don't trap.  */
!   if (!flag_trapping_math && FLOAT_MODE_P (GET_MODE (op)))
      switch (GET_CODE (op))
        {
        case DIV:
diff -p -r -x RCS gcc/gcc/invoke.texi gcc-new/gcc/invoke.texi
*** gcc/gcc/invoke.texi	Wed Feb 28 13:34:34 2001
--- gcc-new/gcc/invoke.texi	Sun Mar  4 21:23:16 2001
*************** in the following sections.
*** 245,252 ****
  -finline-functions  -finline-limit=@var{n}  -fkeep-inline-functions @gol
  -fkeep-static-consts  -fmove-all-movables @gol
  -fno-default-inline  -fno-defer-pop @gol
! -fno-function-cse   -fno-guess-branch-probability
  -fno-inline  -fno-math-errno  -fno-peephole @gol
  -fomit-frame-pointer  -foptimize-register-move @gol
  -foptimize-sibling-calls  -freduce-all-givs @gol
  -fregmove  -frename-registers @gol
--- 245,253 ----
  -finline-functions  -finline-limit=@var{n}  -fkeep-inline-functions @gol
  -fkeep-static-consts  -fmove-all-movables @gol
  -fno-default-inline  -fno-defer-pop @gol
! -fno-function-cse   -fno-guess-branch-probability @gol
  -fno-inline  -fno-math-errno  -fno-peephole @gol
+ -funsafe-math-optimizations -fno-trapping-math @gol
  -fomit-frame-pointer  -foptimize-register-move @gol
  -foptimize-sibling-calls  -freduce-all-givs @gol
  -fregmove  -frename-registers @gol
*************** that alter the assembler output may be c
*** 2934,2944 ****
  performed when this option is not used.
  
  @item -ffast-math
! This option allows GCC to violate some ISO or IEEE rules and/or
! specifications in the interest of optimizing code for speed.  For
! example, it allows the compiler to assume arguments to the @code{sqrt}
! function are non-negative numbers and that no floating-point values
! are NaNs.
  
  This option should never be turned on by any @samp{-O} option since
  it can result in incorrect output for programs which depend on
--- 2935,2942 ----
  performed when this option is not used.
  
  @item -ffast-math
! Sets @samp{-fno-math-errno}, @samp{-funsafe-math-optimizations},
! and @samp{-fno-trapping-math}.
  
  This option should never be turned on by any @samp{-O} option since
  it can result in incorrect output for programs which depend on
*************** with a single instruction, e.g., sqrt.  
*** 2951,2958 ****
--- 2949,2987 ----
  IEEE exceptions for math error handling may want to use this flag
  for speed while maintaining IEEE arithmetic compatibility.
  
+ This option should never be turned on by any @samp{-O} option since
+ it can result in incorrect output for programs which depend on
+ an exact implementation of IEEE or ISO rules/specifications for
+ math functions.
+ 
  The default is @samp{-fmath-errno}.  The @samp{-ffast-math} option
  sets @samp{-fno-math-errno}.
+ 
+ @item -funsafe-math-optimizations
+ Allow optimizations for floating-point arithmetic that (a) assume
+ that arguments and results are valid and (b) may violate IEEE or
+ ANSI standards.  
+ 
+ This option should never be turned on by any @samp{-O} option since
+ it can result in incorrect output for programs which depend on
+ an exact implementation of IEEE or ISO rules/specifications for
+ math functions.
+ 
+ The default is @samp{-fno-unsafe-math-optimizations}.  The
+ @samp{-ffast-math} option sets @samp{-funsafe-math-optimizations}.
+ 
+ @item -fno-trapping-math
+ Compile code assuming that floating-point operations cannot generate
+ user-visible traps.  Setting this option may allow faster code
+ if one relies on "non-stop" IEEE arithmetic, for example.
+ 
+ This option should never be turned on by any @samp{-O} option since
+ it can result in incorrect output for programs which depend on
+ an exact implementation of IEEE or ISO rules/specifications for
+ math functions.
+ 
+ The default is @samp{-ftrapping-math}.  The @samp{-ffast-math}
+ option sets @samp{-fno-trapping-math}.
  @end table
  
  @c following causes underfulls.. they don't look great, but we deal.
*************** Some 387 emulators do not support the @c
*** 6592,6598 ****
  @code{sqrt} instructions for the 387.  Specify this option to avoid
  generating those instructions. This option is the default on FreeBSD.
  As of revision 2.6.1, these instructions are not generated unless you
! also use the @samp{-ffast-math} switch.
  
  @item -malign-double
  @itemx -mno-align-double
--- 6621,6627 ----
  @code{sqrt} instructions for the 387.  Specify this option to avoid
  generating those instructions. This option is the default on FreeBSD.
  As of revision 2.6.1, these instructions are not generated unless you
! also use the @samp{-funsafe-math-optimizations} switch.
  
  @item -malign-double
  @itemx -mno-align-double
Only in gcc/gcc/java: gcj.info
Only in gcc/gcc/java: parse-scan.c
Only in gcc/gcc/java: parse.c
diff -p -r -x RCS gcc/gcc/java/typeck.c gcc-new/gcc/java/typeck.c
*** gcc/gcc/java/typeck.c	Mon Feb 19 17:52:15 2001
--- gcc-new/gcc/java/typeck.c	Sun Mar  4 21:00:36 2001
*************** convert (type, expr)
*** 132,138 ****
      return fold (convert_to_boolean (type, expr));
    if (code == INTEGER_TYPE)
      {
!       if (! flag_fast_math
  	  && ! flag_emit_class_files
  	  && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
  	  && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
--- 132,138 ----
      return fold (convert_to_boolean (type, expr));
    if (code == INTEGER_TYPE)
      {
!       if (! flag_unsafe_math_optimizations
  	  && ! flag_emit_class_files
  	  && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
  	  && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
diff -p -r -x RCS gcc/gcc/jump.c gcc-new/gcc/jump.c
*** gcc/gcc/jump.c	Wed Feb 28 12:49:36 2001
--- gcc-new/gcc/jump.c	Sun Mar  4 21:04:28 2001
*************** reversed_comparison_code_parts (code, ar
*** 1785,1791 ****
  	/* We don't have safe way to reverse these yet - we would need
  	   ordered compares that may not trap.  */
  	if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	    || flag_fast_math)
  	  return reverse_condition_maybe_unordered (code);
  	return UNKNOWN;
        default:
--- 1785,1791 ----
  	/* We don't have safe way to reverse these yet - we would need
  	   ordered compares that may not trap.  */
  	if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	    || flag_unsafe_math_optimizations)
  	  return reverse_condition_maybe_unordered (code);
  	return UNKNOWN;
        default:
*************** reversed_comparison_code_parts (code, ar
*** 1794,1800 ****
  
    /* In case we give up IEEE compatibility, all comparisons are reversible.  */
    if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
!       || flag_fast_math)
      return reverse_condition (code);
  
    if (GET_MODE_CLASS (mode) == MODE_CC
--- 1794,1800 ----
  
    /* In case we give up IEEE compatibility, all comparisons are reversible.  */
    if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
!       || flag_unsafe_math_optimizations)
      return reverse_condition (code);
  
    if (GET_MODE_CLASS (mode) == MODE_CC
*************** rtx_equal_for_thread_p (x, y, yinsn)
*** 4061,4067 ****
       pessimistic, but this pass would only rarely do anything for FP
       anyway.  */
    if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
!       && FLOAT_MODE_P (GET_MODE (x)) && ! flag_fast_math)
      return 0;
  
    /* For commutative operations, the RTX match if the operand match in any
--- 4061,4067 ----
       pessimistic, but this pass would only rarely do anything for FP
       anyway.  */
    if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
!       && FLOAT_MODE_P (GET_MODE (x)) && ! flag_unsafe_math_optimizations)
      return 0;
  
    /* For commutative operations, the RTX match if the operand match in any
diff -p -r -x RCS gcc/gcc/optabs.c gcc-new/gcc/optabs.c
*** gcc/gcc/optabs.c	Sun Feb 18 15:24:10 2001
--- gcc-new/gcc/optabs.c	Sun Mar  4 19:28:57 2001
*************** emit_conditional_move (target, code, op0
*** 3620,3626 ****
    if (((CONSTANT_P (op2) && ! CONSTANT_P (op3))
         || (GET_CODE (op2) == CONST_INT && GET_CODE (op3) != CONST_INT))
        && (GET_MODE_CLASS (GET_MODE (op1)) != MODE_FLOAT
! 	  || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT || flag_fast_math))
      {
        tem = op2;
        op2 = op3;
--- 3620,3627 ----
    if (((CONSTANT_P (op2) && ! CONSTANT_P (op3))
         || (GET_CODE (op2) == CONST_INT && GET_CODE (op3) != CONST_INT))
        && (GET_MODE_CLASS (GET_MODE (op1)) != MODE_FLOAT
! 	  || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT 
! 	  || flag_unsafe_math_optimizations))
      {
        tem = op2;
        op2 = op3;
diff -p -r -x RCS gcc/gcc/simplify-rtx.c gcc-new/gcc/simplify-rtx.c
*** gcc/gcc/simplify-rtx.c	Tue Feb 13 15:43:13 2001
--- gcc-new/gcc/simplify-rtx.c	Sun Mar  4 19:37:11 2001
*************** simplify_binary_operation (code, mode, o
*** 903,909 ****
  	  /* In IEEE floating point, x+0 is not the same as x.  Similarly
  	     for the other optimizations below.  */
  	  if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
! 	      && FLOAT_MODE_P (mode) && ! flag_fast_math)
  	    break;
  
  	  if (op1 == CONST0_RTX (mode))
--- 903,909 ----
  	  /* In IEEE floating point, x+0 is not the same as x.  Similarly
  	     for the other optimizations below.  */
  	  if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
! 	      && FLOAT_MODE_P (mode) && ! flag_unsafe_math_optimizations)
  	    break;
  
  	  if (op1 == CONST0_RTX (mode))
*************** simplify_binary_operation (code, mode, o
*** 1004,1010 ****
  	     In IEEE floating point, x-0 is not the same as x.  */
  
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	       || ! FLOAT_MODE_P (mode) || flag_fast_math)
  	      && op1 == CONST0_RTX (mode))
  	    return op0;
  #endif
--- 1004,1010 ----
  	     In IEEE floating point, x-0 is not the same as x.  */
  
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	       || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
  	      && op1 == CONST0_RTX (mode))
  	    return op0;
  #endif
*************** simplify_binary_operation (code, mode, o
*** 1034,1048 ****
  	  /* None of these optimizations can be done for IEEE
  	     floating point.  */
  	  if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
! 	      && FLOAT_MODE_P (mode) && ! flag_fast_math)
  	    break;
  
  	  /* We can't assume x-x is 0 even with non-IEEE floating point,
  	     but since it is zero except in very strange circumstances, we
! 	     will treat it as zero with -ffast-math.  */
  	  if (rtx_equal_p (op0, op1)
  	      && ! side_effects_p (op0)
! 	      && (! FLOAT_MODE_P (mode) || flag_fast_math))
  	    return CONST0_RTX (mode);
  
  	  /* Change subtraction from zero into negation.  */
--- 1034,1048 ----
  	  /* None of these optimizations can be done for IEEE
  	     floating point.  */
  	  if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
! 	      && FLOAT_MODE_P (mode) && ! flag_unsafe_math_optimizations)
  	    break;
  
  	  /* We can't assume x-x is 0 even with non-IEEE floating point,
  	     but since it is zero except in very strange circumstances, we
! 	     will treat it as zero with -funsafe-math-optimizations.  */
  	  if (rtx_equal_p (op0, op1)
  	      && ! side_effects_p (op0)
! 	      && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations))
  	    return CONST0_RTX (mode);
  
  	  /* Change subtraction from zero into negation.  */
*************** simplify_binary_operation (code, mode, o
*** 1153,1159 ****
  
  	  /* In IEEE floating point, x*0 is not always 0.  */
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	       || ! FLOAT_MODE_P (mode) || flag_fast_math)
  	      && op1 == CONST0_RTX (mode)
  	      && ! side_effects_p (op0))
  	    return op1;
--- 1153,1159 ----
  
  	  /* In IEEE floating point, x*0 is not always 0.  */
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	       || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
  	      && op1 == CONST0_RTX (mode)
  	      && ! side_effects_p (op0))
  	    return op1;
*************** simplify_binary_operation (code, mode, o
*** 1260,1278 ****
  
  	  /* In IEEE floating point, 0/x is not always 0.  */
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	       || ! FLOAT_MODE_P (mode) || flag_fast_math)
  	      && op0 == CONST0_RTX (mode)
  	      && ! side_effects_p (op1))
  	    return op0;
  
  #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
  	  /* Change division by a constant into multiplication.  Only do
! 	     this with -ffast-math until an expert says it is safe in
! 	     general.  */
  	  else if (GET_CODE (op1) == CONST_DOUBLE
  		   && GET_MODE_CLASS (GET_MODE (op1)) == MODE_FLOAT
  		   && op1 != CONST0_RTX (mode)
! 		   && flag_fast_math)
  	    {
  	      REAL_VALUE_TYPE d;
  	      REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
--- 1260,1277 ----
  
  	  /* In IEEE floating point, 0/x is not always 0.  */
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	       || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
  	      && op0 == CONST0_RTX (mode)
  	      && ! side_effects_p (op1))
  	    return op0;
  
  #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
  	  /* Change division by a constant into multiplication.  Only do
! 	     this with -funsafe-math-optimizations.  */
  	  else if (GET_CODE (op1) == CONST_DOUBLE
  		   && GET_MODE_CLASS (GET_MODE (op1)) == MODE_FLOAT
  		   && op1 != CONST0_RTX (mode)
! 		   && flag_unsafe_math_optimizations)
  	    {
  	      REAL_VALUE_TYPE d;
  	      REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
*************** simplify_relational_operation (code, mod
*** 1803,1819 ****
      return simplify_relational_operation (signed_condition (code),
  					  mode, tem, const0_rtx);
  
!   if (flag_fast_math && code == ORDERED)
      return const_true_rtx;
  
!   if (flag_fast_math && code == UNORDERED)
      return const0_rtx;
  
    /* For non-IEEE floating-point, if the two operands are equal, we know the
       result.  */
    if (rtx_equal_p (op0, op1)
        && (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	  || ! FLOAT_MODE_P (GET_MODE (op0)) || flag_fast_math))
      equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0;
  
    /* If the operands are floating-point constants, see if we can fold
--- 1802,1819 ----
      return simplify_relational_operation (signed_condition (code),
  					  mode, tem, const0_rtx);
  
!   if (flag_unsafe_math_optimizations && code == ORDERED)
      return const_true_rtx;
  
!   if (flag_unsafe_math_optimizations && code == UNORDERED)
      return const0_rtx;
  
    /* For non-IEEE floating-point, if the two operands are equal, we know the
       result.  */
    if (rtx_equal_p (op0, op1)
        && (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	  || ! FLOAT_MODE_P (GET_MODE (op0)) 
! 	  || flag_unsafe_math_optimizations))
      equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0;
  
    /* If the operands are floating-point constants, see if we can fold
*************** simplify_ternary_operation (code, mode, 
*** 2082,2093 ****
  
        /* Convert a == b ? b : a to "a".  */
        if (GET_CODE (op0) == NE && ! side_effects_p (op0)
! 	  && (! FLOAT_MODE_P (mode) || flag_fast_math)
  	  && rtx_equal_p (XEXP (op0, 0), op1)
  	  && rtx_equal_p (XEXP (op0, 1), op2))
  	return op1;
        else if (GET_CODE (op0) == EQ && ! side_effects_p (op0)
! 	  && (! FLOAT_MODE_P (mode) || flag_fast_math)
  	  && rtx_equal_p (XEXP (op0, 1), op1)
  	  && rtx_equal_p (XEXP (op0, 0), op2))
  	return op2;
--- 2082,2093 ----
  
        /* Convert a == b ? b : a to "a".  */
        if (GET_CODE (op0) == NE && ! side_effects_p (op0)
! 	  && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
  	  && rtx_equal_p (XEXP (op0, 0), op1)
  	  && rtx_equal_p (XEXP (op0, 1), op2))
  	return op1;
        else if (GET_CODE (op0) == EQ && ! side_effects_p (op0)
! 	  && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
  	  && rtx_equal_p (XEXP (op0, 1), op1)
  	  && rtx_equal_p (XEXP (op0, 0), op2))
  	return op2;
diff -p -r -x RCS gcc/gcc/toplev.c gcc-new/gcc/toplev.c
*** gcc/gcc/toplev.c	Fri Mar  2 16:41:36 2001
--- gcc-new/gcc/toplev.c	Sun Mar  4 21:47:09 2001
*************** int flag_data_sections = 0;
*** 618,639 ****
  
  int flag_no_peephole = 0;
  
- /* Nonzero allows GCC to violate some IEEE or ANSI rules regarding math
-    operations in the interest of optimization.  For example it allows
-    GCC to assume arguments to sqrt are nonnegative numbers, allowing
-    faster code for sqrt to be generated.  */
- 
- int flag_fast_math = 0;
- 
  /* Nonzero allows GCC to optimize sibling and tail recursive calls.  */
  
  int flag_optimize_sibling_calls = 0;
  
  /* Nonzero means the front end generally wants `errno' maintained by math
!    operations, like built-in SQRT, unless overridden by flag_fast_math.  */
  
  int flag_errno_math = 1;
  
  /* 0 means straightforward implementation of complex divide acceptable.
     1 means wide ranges of inputs must work for complex divide.
     2 means C99-like requirements for complex divide (not yet implemented).  */
--- 618,645 ----
  
  int flag_no_peephole = 0;
  
  /* Nonzero allows GCC to optimize sibling and tail recursive calls.  */
  
  int flag_optimize_sibling_calls = 0;
  
  /* Nonzero means the front end generally wants `errno' maintained by math
!    operations, like built-in SQRT.  */
  
  int flag_errno_math = 1;
  
+ /* Nonzero means that unsafe floating-point math optimizations are allowed
+    for the sake of speed.  IEEE compliance is not guaranteed, and operations
+    are allowed to assume that their arguments and results are "normal"
+    (e.g., nonnegative for SQRT).  */
+ 
+ int flag_unsafe_math_optimizations = 0;
+ 
+ /* Zero means that floating-point math operations cannot generate a
+    (user-visible) trap.  This is the case, for example, in nonstop
+    IEEE 754 arithmetic.  */
+ 
+ int flag_trapping_math = 1;
+ 
  /* 0 means straightforward implementation of complex divide acceptable.
     1 means wide ranges of inputs must work for complex divide.
     2 means C99-like requirements for complex divide (not yet implemented).  */
*************** lang_independent_options f_options[] =
*** 1094,1101 ****
     "Reorder basic blocks to improve code placement" },
    {"rename-registers", &flag_rename_registers, 1,
     "Do the register renaming optimization pass"},
-   {"fast-math", &flag_fast_math, 1,
-    "Improve FP speed by violating ANSI & IEEE rules" },
    {"common", &flag_no_common, 0,
     "Do not put unitialised globals in the common section" },
    {"inhibit-size-directive", &flag_inhibit_size_directive, 1,
--- 1100,1105 ----
*************** lang_independent_options f_options[] =
*** 1154,1159 ****
--- 1158,1167 ----
      "Enables guessing of branch probabilities" },
    {"math-errno", &flag_errno_math, 1,
     "Set errno after built-in math functions"},
+   {"trapping-math", &flag_trapping_math, 1,
+    "Floating-point operations can trap"},
+   {"unsafe-math-optimizations", &flag_unsafe_math_optimizations, 1,
+    "Allow math optimizations that may violate IEEE or ANSI standards"},
    {"bounded-pointers", &flag_bounded_pointers, 1,
     "Compile pointers as triples: value, base & end" },
    {"bounds-check", &flag_bounds_check, 1,
*************** lang_independent_options W_options[] =
*** 1479,1484 ****
--- 1487,1512 ----
    {"missing-noreturn", &warn_missing_noreturn, 1,
     "Warn about functions which might be candidates for attribute noreturn"}
  };
+ 
+ /* The following routines are useful in setting all the flags that
+    -ffast-math and -fno-fast-math imply.  */
+ 
+ void
+ set_fast_math_flags ()
+ {
+   flag_trapping_math = 0;
+   flag_unsafe_math_optimizations = 1;
+   flag_errno_math = 0;
+ }
+ 
+ void
+ set_no_fast_math_flags ()
+ {
+   flag_trapping_math = 1;
+   flag_unsafe_math_optimizations = 0;
+   flag_errno_math = 1;
+ }
+ 
  
  /* Output files for assembler code (real compiler output)
     and debugging dumps.  */
*************** decode_f_option (arg)
*** 4093,4100 ****
  	}
      }
  
!   if ((option_value = skip_leading_substring (arg, "inline-limit-"))
!       || (option_value = skip_leading_substring (arg, "inline-limit=")))
      {
        int val = 
  	read_integral_parameter (option_value, arg - 2,
--- 4121,4132 ----
  	}
      }
  
!   if (!strcmp (arg, "fast-math"))
!     set_fast_math_flags();
!   else if (!strcmp (arg, "no-fast-math"))
!     set_no_fast_math_flags();
!   else if ((option_value = skip_leading_substring (arg, "inline-limit-"))
! 	   || (option_value = skip_leading_substring (arg, "inline-limit=")))
      {
        int val = 
  	read_integral_parameter (option_value, arg - 2,
diff -p -r -x RCS gcc/gcc/toplev.h gcc-new/gcc/toplev.h
*** gcc/gcc/toplev.h	Fri Feb 23 16:17:06 2001
--- gcc-new/gcc/toplev.h	Sun Mar  4 20:27:18 2001
*************** struct lang_hooks
*** 163,166 ****
--- 163,172 ----
  /* Each front end provides its own.  */
  extern struct lang_hooks lang_hooks;
  
+ /* These functions can be used by targets to set the flags originally
+    implied by -ffast-math and -fno-fast-math.  */
+ 
+ extern void set_fast_math_flags         PARAMS ((void));
+ extern void set_no_fast_math_flags      PARAMS ((void));
+ 
  #endif /* __GCC_TOPLEV_H */



More information about the Gcc-patches mailing list