diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 984b94167bd6a18e28122e0f843a6e8ec263e1bd..cc9307ec797aed8c478c21062c84aaf8cae6904c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,33 @@
+2002-07-27  Roger Sayle  <roger@eyesopen.com>
+
+	* Makefile.in: rtlanal.o now depends upon real.h.
+
+	* flags.h [flag_signaling_nans]: New flag.
+	[HONOR_SNANS]: New macro.
+
+	* toplev.c [flag_signaling_nans]: Initialize to false.
+        (f_options): Add processing for "-fsignaling-nans".
+	(set_fast_math_flags): Clear flag_signaling_nans with -ffast-math.
+	(process_options): flag_signaling_nans implies flag_trapping_math.
+
+	* c-common.c (cb_register_builtins): Define __SUPPORT_SNAN__
+	when -fsignaling-nans.  First step to implementing WG14's N965.
+
+	* fold-const.c (fold) [MULT_EXPR]: Conditionalize transforming
+	1.0 * x into x, and -1.0 * x into -x on !HONOR_SNANS.
+	[RDIV_EXPR]: Conditionalize x/1.0 into x on !HONOR_SNANS.
+
+	* simplify-rtx.c (simplify_relational_operation): Conditionalize
+	transforming abs(x) < 0.0 into false on !HONOR_SNANS.
+
+	* rtlanal.c: #include real.c for TARGET_FLOAT_FORMAT definitions
+	required by HONOR_SNANS.  (may_trap_p): Floating point DIV, MOD,
+	UDIV, UMOD, GE, GT, LE, LT and COMPARE may always trap with 
+	-fsignaling_nans.  EQ and NE only trap for flag_signaling_nans 
+	not flag_trapping_math (i.e. HONOR_SNANS but not HONOR_NANS).
+
+	* doc/invoke.texi: Document new -fsignaling-nans compiler option.
+
 2002-07-27  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
 	* Makefile.in (gengtype-lex.c): Work around a bug in flex.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 912635cf20982bd5f6c92e8e92e3828d78778759..e87a1ea06261bd673deacd98d362fba99c2233cd 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1403,7 +1403,7 @@ print-rtl.o : print-rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
 	$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
 rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) \
-   hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) flags.h
+   hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) real.h flags.h
 
 errors.o : errors.c $(GCONFIG_H) $(SYSTEM_H) errors.h
 	$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 88c3ef5534dfb79c221d2a727c8361ea440dc2eb..f7bbc1b5f4497ff80a425e92bbb2b76c10180274 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -4383,6 +4383,8 @@ cb_register_builtins (pfile)
     cpp_define (pfile, "__FAST_MATH__");
   if (flag_no_inline)
     cpp_define (pfile, "__NO_INLINE__");
+  if (flag_signaling_nans)
+    cpp_define (pfile, "__SUPPORT_SNAN__");
 
   if (flag_iso)
     cpp_define (pfile, "__STRICT_ANSI__");
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 5240304795f47c201db31f08ac3c94a9be99816d..8d5687b8a014fc440271ca789a20c65838b9f724 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -280,7 +280,7 @@ in the following sections.
 -freduce-all-givs -fregmove  -frename-registers @gol
 -freorder-blocks -freorder-functions @gol
 -frerun-cse-after-loop  -frerun-loop-opt @gol
--fschedule-insns  -fschedule-insns2 @gol
+-fschedule-insns  -fschedule-insns2 -fsignaling-nans @gol
 -fsingle-precision-constant  -fssa -fssa-ccp -fssa-dce @gol
 -fstrength-reduce  -fstrict-aliasing  -ftracer -fthread-jumps  -ftrapv @gol
 -funroll-all-loops  -funroll-loops  @gol
@@ -3407,8 +3407,8 @@ performed when this option is not used.
 
 @item -ffast-math
 @opindex ffast-math
-Sets @option{-fno-math-errno}, @option{-funsafe-math-optimizations}, and @*
-@option{-fno-trapping-math}.
+Sets @option{-fno-math-errno}, @option{-funsafe-math-optimizations}, @*
+@option{-fno-trapping-math} and @option{-fno-signaling-nans}.
 
 This option causes the preprocessor macro @code{__FAST_MATH__} to be defined.
 
@@ -3449,8 +3449,10 @@ The default is @option{-fno-unsafe-math-optimizations}.
 @item -fno-trapping-math
 @opindex 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.
+user-visible traps.  These traps include division by zero, overflow,
+underflow, inexact result and invalid operation.  This option implies
+@option{-fno-signaling-nans}.  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 @option{-O} option since
 it can result in incorrect output for programs which depend on
@@ -3459,6 +3461,21 @@ math functions.
 
 The default is @option{-ftrapping-math}.
 
+@item -fsignaling-nans
+@opindex fsignaling-nans
+Compile code assuming that IEEE signaling NaNs may generate user-visible
+traps during floating-point operations.  Setting this option disables
+optimizations that may change the number of exceptions visible with
+signaling NaNs.  This option implies @option{-ftrapping-math}.
+
+This option causes the preprocessor macro @code{__SUPPORT_SNAN__} to
+be defined.
+
+The default is @option{-fno-signaling-nans}.
+
+This option is experimental and does not currently guarantee to
+disable all GCC optimizations that affect signaling NaN behavior.
+
 @item -fno-zero-initialized-in-bss
 @opindex fno-zero-initialized-in-bss
 If the target supports a BSS section, GCC by default puts variables that
diff --git a/gcc/flags.h b/gcc/flags.h
index 012b63c8d4511a48f2725166d8de4b11f977100e..06ebd20a59d5ef15e4e94b7fc61cbb830572cffc 100644
--- a/gcc/flags.h
+++ b/gcc/flags.h
@@ -663,6 +663,9 @@ extern int flag_non_call_exceptions;
 /* Nonzero means put zero initialized data in the bss section.  */
 extern int flag_zero_initialized_in_bss;
 
+/* Nonzero means disable transformations observable by signaling NaNs.  */
+extern int flag_signaling_nans;
+
 /* True if the given mode has a NaN representation and the treatment of
    NaN operands is important.  Certain optimizations, such as folding
    x * 0 into x, are not correct for NaN operands, and are normally
@@ -671,6 +674,9 @@ extern int flag_zero_initialized_in_bss;
 #define HONOR_NANS(MODE) \
   (MODE_HAS_NANS (MODE) && !flag_unsafe_math_optimizations)
 
+/* Like HONOR_NANs, but true if we honor signaling NaNs (or sNaNs).  */
+#define HONOR_SNANS(MODE) (flag_signaling_nans && HONOR_NANS (MODE))
+
 /* As for HONOR_NANS, but true if the mode can represent infinity and
    the treatment of infinite values is important.  */
 #define HONOR_INFINITIES(MODE) \
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 3dafe0afb31115f095a91e97096d33585630f4ec..49c53cc0857daf3600ab9caab5873d05c0a77a22 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -5476,16 +5476,13 @@ fold (expr)
 	      && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
 	      && real_zerop (arg1))
 	    return omit_one_operand (type, arg1, arg0);
-	  /* In IEEE floating point, x*1 is not equivalent to x for snans.
-	     However, ANSI says we can drop signals,
-	     so we can do this anyway.  */
-	  if (real_onep (arg1))
+	  /* In IEEE floating point, x*1 is not equivalent to x for snans.  */
+	  if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+	      && real_onep (arg1))
 	    return non_lvalue (convert (type, arg0));
 
-	  /* Transform x * -1.0 into -x.  This should be safe for NaNs,
-	     signed zeros and signed infinities, but is currently
-	     restricted to "unsafe math optimizations" just in case.  */
-	  if (flag_unsafe_math_optimizations
+	  /* Transform x * -1.0 into -x.  */
+	  if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
 	      && real_minus_onep (arg1))
 	    return fold (build1 (NEGATE_EXPR, type, arg0));
 
@@ -5620,9 +5617,9 @@ fold (expr)
 	return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
 			    TREE_OPERAND (arg1, 0)));
 
-      /* In IEEE floating point, x/1 is not equivalent to x for snans.
-	 However, ANSI says we can drop signals, so we can do this anyway.  */
-      if (real_onep (arg1))
+      /* In IEEE floating point, x/1 is not equivalent to x for snans.  */
+      if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+	  && real_onep (arg1))
 	return non_lvalue (convert (type, arg0));
 
       /* If ARG1 is a constant, we can convert this to a multiply by the
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 35cc5130caaa0a5a7d0ec4f9ace1705ad7832290..6d391eaf374b55773a09686c3f2a1e50a28faaba 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -30,6 +30,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm_p.h"
 #include "flags.h"
 #include "basic-block.h"
+#include "real.h"
 
 /* Forward declarations */
 static int global_reg_mentioned_p_1 PARAMS ((rtx *, void *));
@@ -2369,6 +2370,8 @@ may_trap_p (x)
     case MOD:
     case UDIV:
     case UMOD:
+      if (HONOR_SNANS (GET_MODE (x)))
+	return 1;
       if (! CONSTANT_P (XEXP (x, 1))
 	  || (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
 	      && flag_trapping_math))
@@ -2396,12 +2399,22 @@ may_trap_p (x)
 	 when COMPARE is used, though many targets do make this distinction.
 	 For instance, sparc uses CCFPE for compares which generate exceptions
 	 and CCFP for compares which do not generate exceptions.  */
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+      if (HONOR_NANS (GET_MODE (x)))
 	return 1;
       /* But often the compare has some CC mode, so check operand
 	 modes as well.  */
-      if (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) == MODE_FLOAT
-	  || GET_MODE_CLASS (GET_MODE (XEXP (x, 1))) == MODE_FLOAT)
+      if (HONOR_NANS (GET_MODE (XEXP (x, 0)))
+	  || HONOR_NANS (GET_MODE (XEXP (x, 1))))
+	return 1;
+      break;
+
+    case EQ:
+    case NE:
+      if (HONOR_SNANS (GET_MODE (x)))
+	return 1;
+      /* Often comparison is CC mode, so check operand modes.  */
+      if (HONOR_SNANS (GET_MODE (XEXP (x, 0)))
+	  || HONOR_SNANS (GET_MODE (XEXP (x, 1))))
 	return 1;
       break;
 
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 59f9aa6d37b390b9c82a9e7d8ab5cda5753cd5a3..0565dcd32b888dcd0c0f92a85a92a8d66c83c0a1 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -2063,7 +2063,7 @@ simplify_relational_operation (code, mode, op0, op1)
 
 	case LT:
 	  /* Optimize abs(x) < 0.0.  */
-	  if (trueop1 == CONST0_RTX (mode))
+	  if (trueop1 == CONST0_RTX (mode) && !HONOR_SNANS (mode))
 	    {
 	      tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
 						       : trueop0;
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 0022fcb289cb67f9a5a50883ff939b98dd9bf481..e4aeca03875e44f2b39b8805830eb924914270b4 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -577,10 +577,18 @@ 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.  */
+   IEEE 754 arithmetic.  Trapping conditions include division by zero,
+   overflow, underflow, invalid and inexact, but does not include 
+   operations on signaling NaNs (see below).  */
 
 int flag_trapping_math = 1;
 
+/* Nonzero means disable transformations observable by signaling NaNs.
+   This option implies that any operation on a IEEE signaling NaN can
+   generate a (user-visible) trap.  */
+
+int flag_signaling_nans = 0;
+
 /* 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).  */
@@ -1170,6 +1178,8 @@ static const lang_independent_options f_options[] =
    N_("Floating-point operations can trap") },
   {"unsafe-math-optimizations", &flag_unsafe_math_optimizations, 1,
    N_("Allow math optimizations that may violate IEEE or ANSI standards") },
+  {"signaling-nans", &flag_signaling_nans, 1,
+   N_("Disable optimizations observable by IEEE signaling NaNs") },
   {"bounded-pointers", &flag_bounded_pointers, 1,
    N_("Compile pointers as triples: value, base & end") },
   {"bounds-check", &flag_bounds_check, 1,
@@ -1566,6 +1576,8 @@ set_fast_math_flags (set)
   flag_trapping_math = !set;
   flag_unsafe_math_optimizations = set;
   flag_errno_math = !set;
+  if (set)
+    flag_signaling_nans = 0;
 }
 
 /* Return true iff flags are set as if -ffast-math.  */
@@ -5086,6 +5098,10 @@ process_options ()
   if (flag_function_sections && write_symbols != NO_DEBUG)
     warning ("-ffunction-sections may affect debugging on some targets");
 #endif
+
+    /* The presence of IEEE signaling NaNs, implies all math can trap.  */
+    if (flag_signaling_nans)
+      flag_trapping_math = 1;
 }
 
 /* Language-independent initialization, before language-dependent