This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Making double precision constants work with -fsingle-precision-constant
- From: Carlos O'Donell <carlos at codesourcery dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org, "Joseph S. Myers" <joseph at codesourcery dot com>
- Date: Wed, 7 Dec 2005 14:25:08 -0500
- Subject: Re: [PATCH] Making double precision constants work with -fsingle-precision-constant
- References: <20051129021133.GB14313@lios> <20051129051045.GA19722@redhat.com>
On Mon, Nov 28, 2005 at 09:10:45PM -0800, Richard Henderson wrote:
> That said, I'd prefer that we used constants when possible.
> I.e. this cast horridness should never be seen unless the
> user uses that option.
Ok.
Constants are only used when required e.g. flag_single_precision_constant
is set. Tested with no regressions on x86-pc-linux-gnu and x86_64-pc-linux-gnu.
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.
(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
[__DBL_DENORM_MIN__] (struct numeric_limits): Set denorm_present.
[!__DBL_DENORM_MIN__] (struct numeric_limits): Set denorm_absent.
Index: gcc/c-cppbuiltin.c
===================================================================
--- gcc/c-cppbuiltin.c (revision 108064)
+++ 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,7 +242,7 @@
{
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);
}
else
{
@@ -382,9 +389,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 +594,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 +614,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 108064)
+++ 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 defined __DBL_DENORM_MIN__
+ 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()