This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Making double precision constants work with -fsingle-precision-constant


On Fri, Dec 09, 2005 at 12:31:44PM -0800, Mark Mitchell wrote:
> Richard Henderson wrote:
> > On Thu, Dec 08, 2005 at 11:48:54AM -0500, Carlos O'Donell wrote:
> > 
> >>Would it be useful to define __DBL_HAS_DENORM__, it is already a
> >>property of the format (gcc/gcc/real.h)?
> >  
> > I didn't think it was useful before, but now it would appear
> > to be required.  Supposing we keep this option.
> 
> I guess I think we should fix the bug.  So, Carlos, would you add
> __DBL_HAS_DENORM__ and then revise the libstdc++ changes, since we need
> __DBL_HAS_DENORM__ to make the libstdc++ changes correct?

Yes it's required to have std_limits.h compile when
-fsingle-precision-constant is enabled.

> We've advised our customer that there's not a lot of love of the option.
> and that it might go away.  They feel it's a useful option for embedded
> users who are reusing workstation code in an embedded environment, where
> doubles are expensive.  (I wonder what happens -- or should happen, even
> -- when you use this option with a double-precision constant.)  I've
> advised them that if they feel strongly about keeping this option in the
> long term, they should make their case here.

Retested no regresssions on x86-pc-linux-gnu. This adds additional
macros __*_HAS_DENORM__ of which __DBL_HAS_DENORM__ is used in std_limits.h.

2005-11-30  Carlos O'Donell <carlos@codesourcery.com>
                                                 
	* gcc/c-cppbuiltin.c (builtin_define_float_constants): Add
	fp_cast parameter, pass to builtin_define_with_hex_fp_value.
	Define __FLT_HAS_DENORM__, __DBL_HAS_DENORM__, __LDBL_HAS_DENORM__.
	(builtin_define_with_hex_fp_value): Use fp_cast when building macro.
	(c_cpp_builtins): If flag_single_precision_constant then set fp_cast
	to "((double)%sL)" otherwise "%s".
	* libstdc++-v3/include/std/std_limits.h
	(struct numeric_limits): if __DBL_HAS_DENORM__ is 1 set
        has_denorm to denorm_present otherwise denorm_absent.

Index: gcc/c-cppbuiltin.c
===================================================================
--- gcc/c-cppbuiltin.c	(revision 108317)
+++ gcc/c-cppbuiltin.c	(working copy)
@@ -53,11 +53,14 @@
 static void builtin_define_with_int_value (const char *, HOST_WIDE_INT);
 static void builtin_define_with_hex_fp_value (const char *, tree,
 					      int, const char *,
+					      const char *,
 					      const char *);
 static void builtin_define_stdint_macros (void);
 static void builtin_define_type_max (const char *, tree, int);
 static void builtin_define_type_precision (const char *, tree);
-static void builtin_define_float_constants (const char *, const char *,
+static void builtin_define_float_constants (const char *, 
+					    const char *,
+					    const char *,
 					    tree);
 static void define__GNUC__ (void);
 
@@ -68,9 +71,13 @@
   builtin_define_with_int_value (name, TYPE_PRECISION (type));
 }
 
-/* Define the float.h constants for TYPE using NAME_PREFIX and FP_SUFFIX.  */
+/* Define the float.h constants for TYPE using NAME_PREFIX, FP_SUFFIX,
+   and FP_CAST. */
 static void
-builtin_define_float_constants (const char *name_prefix, const char *fp_suffix, tree type)
+builtin_define_float_constants (const char *name_prefix, 
+		                const char *fp_suffix, 
+				const char *fp_cast, 
+				tree type)
 {
   /* Used to convert radix-based values to base 10 values in several cases.
 
@@ -208,13 +215,13 @@
       }
   }
   sprintf (name, "__%s_MAX__", name_prefix);
-  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
+  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
 
   /* The minimum normalized positive floating-point number,
      b**(emin-1).  */
   sprintf (name, "__%s_MIN__", name_prefix);
   sprintf (buf, "0x1p%d", (fmt->emin - 1) * fmt->log2_b);
-  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
+  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
 
   /* The difference between 1 and the least value greater than 1 that is
      representable in the given floating point type, b**(1-p).  */
@@ -225,7 +232,7 @@
       sprintf (buf, "0x1p%d", (fmt->emin - fmt->p) * fmt->log2_b);
     else      
       sprintf (buf, "0x1p%d", (1 - fmt->p) * fmt->log2_b);
-  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
+  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
 
   /* For C++ std::numeric_limits<T>::denorm_min.  The minimum denormalized
      positive floating-point number, b**(emin-p).  Zero for formats that
@@ -235,12 +242,18 @@
     {
       sprintf (buf, "0x1p%d", (fmt->emin - fmt->p) * fmt->log2_b);
       builtin_define_with_hex_fp_value (name, type, decimal_dig,
-					buf, fp_suffix);
+					buf, fp_suffix, fp_cast);
+      /* denorm is present */
+      sprintf (name, "__%s_HAS_DENORM__", name_prefix);
+      builtin_define_with_value (name, "1", 0);
     }
   else
     {
       sprintf (buf, "0.0%s", fp_suffix);
       builtin_define_with_value (name, buf, 0);
+      /* denorm is not present */
+      sprintf (name, "__%s_HAS_DENORM__", name_prefix);
+      builtin_define_with_value (name, "0", 0);
     }
 
   /* For C++ std::numeric_limits<T>::has_infinity.  */
@@ -382,9 +395,16 @@
   builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
 				 TARGET_FLT_EVAL_METHOD);
 
-  builtin_define_float_constants ("FLT", "F", float_type_node);
-  builtin_define_float_constants ("DBL", "", double_type_node);
-  builtin_define_float_constants ("LDBL", "L", long_double_type_node);
+  builtin_define_float_constants ("FLT", "F", "%s", float_type_node);
+  /* Cast the double precision constants when single precision constants are
+     specified. The correct result is computed by the compiler when using 
+     macros that include a cast. This has the side-effect of making the value 
+     unusable in const expressions. */
+  if (flag_single_precision_constant)
+    builtin_define_float_constants ("DBL", "L", "((double)%s)", double_type_node);
+  else
+    builtin_define_float_constants ("DBL", "", "%s", double_type_node);
+  builtin_define_float_constants ("LDBL", "L", "%s", long_double_type_node);
 
   /* For use in assembly language.  */
   builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0);
@@ -580,10 +600,12 @@
 static void
 builtin_define_with_hex_fp_value (const char *macro,
 				  tree type ATTRIBUTE_UNUSED, int digits,
-				  const char *hex_str, const char *fp_suffix)
+				  const char *hex_str, 
+				  const char *fp_suffix,
+				  const char *fp_cast)
 {
   REAL_VALUE_TYPE real;
-  char dec_str[64], buf[256];
+  char dec_str[64], buf1[256], buf2[256];
 
   /* Hex values are really cool and convenient, except that they're
      not supported in strict ISO C90 mode.  First, the "p-" sequence
@@ -598,8 +620,13 @@
   real_from_string (&real, hex_str);
   real_to_decimal (dec_str, &real, sizeof (dec_str), digits, 0);
 
-  sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix);
-  cpp_define (parse_in, buf);
+  /* Assemble the macro in the following fashion
+     macro = fp_cast [dec_str fp_suffix] */
+  sprintf (buf1, "%s%s", dec_str, fp_suffix);
+  sprintf (buf2, fp_cast, buf1);
+  sprintf (buf1, "%s=%s", macro, buf2);
+  
+  cpp_define (parse_in, buf1);
 }
 
 /* Define MAX for TYPE based on the precision of the type.  IS_LONG is
Index: libstdc++-v3/include/std/std_limits.h
===================================================================
--- libstdc++-v3/include/std/std_limits.h	(revision 108317)
+++ libstdc++-v3/include/std/std_limits.h	(working copy)
@@ -1063,8 +1063,11 @@
       static const bool has_infinity = __DBL_HAS_INFINITY__;
       static const bool has_quiet_NaN = __DBL_HAS_QUIET_NAN__;
       static const bool has_signaling_NaN = has_quiet_NaN;
-      static const float_denorm_style has_denorm
-	= bool(__DBL_DENORM_MIN__) ? denorm_present : denorm_absent;
+#if __DBL_HAS_DENORM__
+      static const float_denorm_style has_denorm = denorm_present;
+#else
+      static const float_denorm_style has_denorm = denorm_absent;
+#endif
       static const bool has_denorm_loss = __glibcxx_double_has_denorm_loss;
 
       static double infinity() throw()


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]