diff mbox

Cache reals for 1/4, 1/6 and 1/9

Message ID 87si5pbcev.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford Oct. 5, 2015, 2:47 p.m. UTC
Richard Biener <richard.guenther@gmail.com> writes:
> On Thu, Oct 1, 2015 at 3:59 PM, Bernd Schmidt <bschmidt@redhat.com> wrote:
>> On 10/01/2015 03:51 PM, Richard Sandiford wrote:
>>>
>>> We have a global 1/2 and a cached 1/3, but recalculate 1/4, 1/6 and 1/9
>>> each time we need them.  That seems a bit arbitrary and makes the folding
>>> code more noisy (especially once it's moved to match.pd).
>>>
>>> This patch caches the other three constants too.  Bootstrapped &
>>> regression-tested on x86_64-linux-gnu.  OK to install?
>>
>>
>> Looks reasonable enough.
>
> Given
>
> /* Returns the special REAL_VALUE_TYPE corresponding to 1/3.  */
>
> const REAL_VALUE_TYPE *
> dconst_third_ptr (void)
> {
>   static REAL_VALUE_TYPE value;
>
>   /* Initialize mathematical constants for constant folding builtins.
>      These constants need to be given to at least 160 bits precision.  */
>   if (value.cl == rvc_zero)
>     {
>       real_arithmetic (&value, RDIV_EXPR, &dconst1, real_digit (3));
>     }
>   return &value;
> }
>
> I wonder if it makes sense to have
>
> template<int a, int b>
> const REAL_VALUE_TYPE &
> dconst (void)
> {
>   static REAL_VALUE_TYPE value;
>   if (value.cl == rvc_zero)
>     real_arithmetic (&value, RDIV_EXPR, real_digit (a), real_digit (b));
>   return value;
> }
>
> instead which allows us to use
>
>   dconst<1,2>()
>
> in place of dconst_half () and allows arbitrary extra cached constants to be
> added (well, double-check that, but I think the function static should be
> a .comdat).

You suggested on IRC that we do the same for the integral constants,
so e.g. dconst0 becomes dconst<0> ().  Here's the result.  Like I said,
I think this may be a case of "be careful what you wish for".

Bootstrapped & regression-tested on x86_64-linux-gnu.  Also tested by
building one target per CPU directory and checking that there were no
new warnings and no changes in testsuite output at -O2.  OK to install?

Thanks,
Richard


gcc/ada/
	* gcc-interface/trans.c (convert_with_check): Use dconst template
	instead of static variables.

gcc/c-family/
	* c-common.c (c_common_truthvalue_conversion): Use dconst template
	instead of static variables.
	* c-lex.c (interpret_float): Likewise.
	* c-ubsan.c (ubsan_instrument_division): Likewise.

gcc/java/
	* decl.c (java_init_decl_processing): Use dconst template instead
	of static variables.

gcc/
	* real.h (dconst0, dconst1, dconst2, dconstm1, dconsthalf): Delete.
	(dconst_third, dconst_third_ptr): Delete.
	(real_from_fraction): Declare.
	(dconst): New function.
	* real.c (real_from_fraction): New function.
	(real_digit, dconst_third_ptr): Delete.
	(exact_real_inverse, real_to_decimal_for_mode, decimal_integer_string)
	(ten_to_mptwo, times_pten): Use dconst instead of real_digit.
	(real_powi, real_floor, real_ceil, real_round): Use dconst
	instead of static variables.
	* emit-rtl.c (dconst0, dconst1, dconst2, dconstm1, dconsthalf): Delete.
	(init_emit_once): Don't initialize them.
	* builtins.c (fold_builtin_sqrt, fold_builtin_cbrt): Use dconst
	instead of static variables.  Also use dconst<1, 6> and dconst<1, 9>
	instead of deriving them from doncst_third.
	(expand_builtin_cexpi, expand_builtin_signbit, fold_builtin_cabs)
	(fold_builtin_pow, fold_builtin_powi, fold_builtin_signbit)
	(fold_builtin_modf, fold_builtin_classify, fold_builtin_fpclassify)
	(fold_builtin_1, fold_builtin_2): Use dconst instead of static
	variables.
	* doc/match-and-simplify.texi: Likewise (in examples).
	* config/aarch64/aarch64.c (aarch64_float_const_zero_rtx_p): Likewise.
	* config/c6x/c6x.md (divsf3, divdf3): Likewise.
	* config/fr30/fr30.c (fr30_const_double_is_zero): Likewise.
	* config/i386/i386.c (standard_80387_constant_p): Likewise.
	(ix86_expand_convert_uns_didf_sse, ix86_expand_convert_uns_sidf_sse)
	(ix86_expand_convert_sign_didf_sse, ix86_expand_convert_uns_sisf_sse)
	(ix86_expand_vector_convert_uns_vsivsf): Likewise.
	(ix86_expand_adjust_ufix_to_sfix_si, ix86_emit_i387_round): Likewise.
	(ix86_emit_swsqrtsf, ix86_gen_TWO52, ix86_expand_lround): Likewise.
	(ix86_expand_floorceildf_32, ix86_expand_floorceil): Likewise.
	(ix86_expand_rounddf_32, ix86_expand_truncdf_32): Likewise.
	(ix86_expand_round, ix86_expand_round_sse4): Likewise.
	* config/i386/i386.md (fixuns_trunc<mode>si2): Likewise.
	* config/i386/sse.md (vec_unpacku_float_hi_v4si): Likewise.
	(vec_unpacku_float_lo_v4si, vec_unpacku_float_hi_v8si): Likewise.
	(vec_unpacku_float_hi_v16si, vec_unpacku_float_lo_v8si): Likewise.
	(vec_unpacku_float_lo_v16si, round<mode>2): Likewise.
	* config/m68k/m68k.c (floating_exact_log2): Likewise.
	* config/rs6000/rs6000.c (rs6000_emit_swdiv): Likewise.
	(rs6000_scale_v2df): Likewise.
	* config/rs6000/rs6000.md (*cmptf_internal2): Likewise.
	* config/sh/sh.c (fp_zero_operand, fp_one_operand): Likewise.
	* config/xtensa/predicates.md (const_float_1_operand): Likewise.
	* cprop.c (implicit_set_cond_p): Likewise.
	* dfp.c (decimal_to_decnumber): Likewise.
	* expmed.c (expand_mult): Likewise.
	* fold-const.c (const_binop, distribute_real_division): Likewise.
	(fold_binary_loc): Likewise.
	* match.pd: Likewise throughout.
	* simplify-rtx.c (simplify_binary_operation_1): Likewise.
	(simplify_const_binary_operation): Likewise.
	* tree-call-cdce.c (check_pow): Likewise.
	(gen_conditions_for_pow_cst_base): Likewise.
	* tree-chrec.c (chrec_fold_plus_poly_poly): Likewise.
	(chrec_fold_multiply_poly_poly, chrec_fold_plus_1): Likewise.
	* tree-complex.c (some_nonzerop, get_component_ssa_name): Likewise.
	(expand_complex_multiplication): Likewise.
	* tree-inline.c (estimate_num_insns): Likewise.
	* tree-scalar-evolution.c (add_to_evolution_1): Likewise.
	(add_to_evolution): Likewise.
	* tree-ssa-dom.c (record_equality): Likewise.
	* tree-ssa-math-opts.c (powi_as_mults): Likewise.
	(representable_as_half_series_p, expand_pow_as_sqrts): Likewise.
	(pass_cse_sincos::execute): Likewise.
	(pass_optimize_widening_mul::execute): Likewise.
	(gimple_expand_builtin_pow): Likewise.  Use dconst instead of
	local variables for 3 and 1/4.
	* tree-ssa-uncprop.c (associate_equivalences_with_edges): Use dconst
	instead of static variables.
	* tree-vect-loop.c (get_initial_def_for_reduction): Likewise.
	* tree-vect-patterns.c (vect_recog_pow_pattern): Likewise.
	* tree-vect-slp.c (vect_get_constant_vectors): Likewise.
	* tree.c (build_one_cst, build_minus_one_cst, build_zero_cst)
	(real_zerop, real_onep, real_minus_onep): Likewise.
	* ubsan.c (ubsan_instrument_float_cast): Likewise.

Comments

Bernd Schmidt Oct. 5, 2015, 2:40 p.m. UTC | #1
On 10/05/2015 04:47 PM, Richard Sandiford wrote:
> @@ -9536,7 +9520,7 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
>   	{
>   	  r = TREE_REAL_CST (arg);
>   	  if (real_isinf (&r))
> -	    return real_compare (GT_EXPR, &r, &dconst0)
> +	    return real_compare (GT_EXPR, &r, &dconst<0> ())
>   		   ? integer_one_node : integer_minus_one_node;
>   	  else
>   	    return integer_zero_node;

So... are the templates magic enough not to make us create a new 
temporary every time this is used?


Bernd
Bernd Schmidt Oct. 5, 2015, 3:10 p.m. UTC | #2
On 10/05/2015 05:22 PM, Richard Sandiford wrote:
> Bernd Schmidt <bschmidt@redhat.com> writes:
>> On 10/05/2015 04:47 PM, Richard Sandiford wrote:
>>> @@ -9536,7 +9520,7 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
>>>    	{
>>>    	  r = TREE_REAL_CST (arg);
>>>    	  if (real_isinf (&r))
>>> -	    return real_compare (GT_EXPR, &r, &dconst0)
>>> +	    return real_compare (GT_EXPR, &r, &dconst<0> ())
>>>    		   ? integer_one_node : integer_minus_one_node;
>>>    	  else
>>>    	    return integer_zero_node;
>>
>> So... are the templates magic enough not to make us create a new
>> temporary every time this is used?
>
> Yeah, the static variables become comdat objects keyed off the full name
> (dconst<...>::value).  They're shared between calls and between TUs.

Hmm. And since you're returning a reference, taking the address works. 
The whole thing is subtle enough that it deserves a comment. Since this 
kind of thing is something I don't like about C++ (simple-looking code 
expanding into non-obvious behaviour) I'm not going to ack this patch, 
but if someone else wants to, that's fine.

I do believe you still have some code growth since the inline dconst 
function always expands code that will initialize the constant. IMO 
that's not desirable.


Bernd
Richard Sandiford Oct. 5, 2015, 3:22 p.m. UTC | #3
Bernd Schmidt <bschmidt@redhat.com> writes:
> On 10/05/2015 04:47 PM, Richard Sandiford wrote:
>> @@ -9536,7 +9520,7 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
>>   	{
>>   	  r = TREE_REAL_CST (arg);
>>   	  if (real_isinf (&r))
>> -	    return real_compare (GT_EXPR, &r, &dconst0)
>> +	    return real_compare (GT_EXPR, &r, &dconst<0> ())
>>   		   ? integer_one_node : integer_minus_one_node;
>>   	  else
>>   	    return integer_zero_node;
>
> So... are the templates magic enough not to make us create a new 
> temporary every time this is used?

Yeah, the static variables become comdat objects keyed off the full name
(dconst<...>::value).  They're shared between calls and between TUs.

Thanks,
Richard
Bernd Schmidt Oct. 5, 2015, 4:52 p.m. UTC | #4
On 10/05/2015 07:00 PM, Richard Sandiford wrote:
>
> If my original patch isn't acceptable,

I thought I'd approved it.

> another old-school way of doing
> it would be to have a .def file of all the constants that we want.
> They could then all be global variables, rather than having some that
> are and some that aren't.  They could be initialised at the same point
> that dconst0 etc. are initialised now.

The thought had crossed my mind, but how many such constants are there, 
really? All this seems like a bigger hammer than necessary.


Bernd
Richard Sandiford Oct. 5, 2015, 5 p.m. UTC | #5
Bernd Schmidt <bschmidt@redhat.com> writes:
> On 10/05/2015 05:22 PM, Richard Sandiford wrote:
>> Bernd Schmidt <bschmidt@redhat.com> writes:
>>> On 10/05/2015 04:47 PM, Richard Sandiford wrote:
>>>> @@ -9536,7 +9520,7 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
>>>>    	{
>>>>    	  r = TREE_REAL_CST (arg);
>>>>    	  if (real_isinf (&r))
>>>> -	    return real_compare (GT_EXPR, &r, &dconst0)
>>>> +	    return real_compare (GT_EXPR, &r, &dconst<0> ())
>>>>    		   ? integer_one_node : integer_minus_one_node;
>>>>    	  else
>>>>    	    return integer_zero_node;
>>>
>>> So... are the templates magic enough not to make us create a new
>>> temporary every time this is used?
>>
>> Yeah, the static variables become comdat objects keyed off the full name
>> (dconst<...>::value).  They're shared between calls and between TUs.
>
> Hmm. And since you're returning a reference, taking the address works. 
> The whole thing is subtle enough that it deserves a comment. Since this 
> kind of thing is something I don't like about C++ (simple-looking code 
> expanding into non-obvious behaviour) I'm not going to ack this patch, 
> but if someone else wants to, that's fine.
>
> I do believe you still have some code growth since the inline dconst 
> function always expands code that will initialize the constant. IMO 
> that's not desirable.

I don't disagree.  I find dconst0 much easier to read than dconst<0> ().
In some ways I was posting the patch to show how bad it could be :-)

If we're prepared to pay the cost of unconditional load-time
initialisation, we could have:

template <int N>
struct dconst_value
{
  dconst_value () { ...set up value ...; }
  REAL_VALUE_TYPE value;
};

template <int N>
const REAL_VALUE_TYPE &
dconst<T> (void)
{
  static dconst_value<N> x;
  return x.value;
}

But this feels like using templates just to prove we know how they work,
rather than because they're the right tool for the job.

If my original patch isn't acceptable, another old-school way of doing
it would be to have a .def file of all the constants that we want.
They could then all be global variables, rather than having some that
are and some that aren't.  They could be initialised at the same point
that dconst0 etc. are initialised now.

E.g. we could have dconst1_3 for 1/3, dconst1_9 for 1/9, etc.  There's
a slight problem that those names are already used for local, rounded,
versions of the constants in some places, but that's easy to fix.

Thanks,
Richard
Marc Glisse Oct. 5, 2015, 5:29 p.m. UTC | #6
On Mon, 5 Oct 2015, Richard Sandiford wrote:

>> I do believe you still have some code growth since the inline dconst
>> function always expands code that will initialize the constant. IMO
>> that's not desirable.
>
> I don't disagree.  I find dconst0 much easier to read than dconst<0> ().
> In some ways I was posting the patch to show how bad it could be :-)
>
> If we're prepared to pay the cost of unconditional load-time
> initialisation, we could have:
>
> template <int N>
> struct dconst_value
> {
>  dconst_value () { ...set up value ...; }
>  REAL_VALUE_TYPE value;
> };
>
> template <int N>
> const REAL_VALUE_TYPE &
> dconst<T> (void)
> {
>  static dconst_value<N> x;
>  return x.value;
> }

Why are you calling this load-time initialization? As far as I know, such 
a static object is still initialized lazily (with all the overhead this 
implies). Did you mean to make value a static member of dconst_value?
Mike Stump Oct. 5, 2015, 6:04 p.m. UTC | #7
On Oct 5, 2015, at 7:47 AM, Richard Sandiford <richard.sandiford@arm.com> wrote:
> -      return real_equal (&TREE_REAL_CST (expr), &dconst0)
> +      return real_equal (&TREE_REAL_CST (expr), &dconst<0> ())

On behalf of mere mortals, hiding the syntax &dconst<0> () into a header file as in implementation detail is entirely reasonable.


  return real_equal (&TREE_REAL_CST (expr), &double_const(0))

Also, in C++, we don’t like to mandate apis use & on their parameters, so the nicer form:

  return real_equal (TREE_REAL_CST (expr), double_const(0))

is preferred.  :-)  One you add conversion operators:

  return real_equal (TREE_REAL_CST (expr), 0)

and then with operator support, (if == would not be too confusing given the actual semantic of real_equal):

  return TREE_REAL_CST (expr) == 0;

and possibly even just:

  return expr == 0

in the end.  :-)
Richard Biener Oct. 5, 2015, 6:52 p.m. UTC | #8
On October 5, 2015 8:04:59 PM GMT+02:00, Mike Stump <mikestump@comcast.net> wrote:
>On Oct 5, 2015, at 7:47 AM, Richard Sandiford
><richard.sandiford@arm.com> wrote:
>> -      return real_equal (&TREE_REAL_CST (expr), &dconst0)
>> +      return real_equal (&TREE_REAL_CST (expr), &dconst<0> ())
>
>On behalf of mere mortals, hiding the syntax &dconst<0> () into a
>header file as in implementation detail is entirely reasonable.

That would mean using references as parameters.  I think we decided against this to make it more explicit what is a pointer and what not.

>
>  return real_equal (&TREE_REAL_CST (expr), &double_const(0))
>
>Also, in C++, we don’t like to mandate apis use & on their parameters,
>so the nicer form:
>
>  return real_equal (TREE_REAL_CST (expr), double_const(0))
>
>is preferred.  :-)  One you add conversion operators:
>
>  return real_equal (TREE_REAL_CST (expr), 0)
>
>and then with operator support, (if == would not be too confusing given
>the actual semantic of real_equal):
>
>  return TREE_REAL_CST (expr) == 0;
>
>and possibly even just:
>
>  return expr == 0
>
>in the end.  :-)

Aww...
Richard Sandiford Oct. 5, 2015, 7:40 p.m. UTC | #9
Marc Glisse <marc.glisse@inria.fr> writes:
> On Mon, 5 Oct 2015, Richard Sandiford wrote:
>
>>> I do believe you still have some code growth since the inline dconst
>>> function always expands code that will initialize the constant. IMO
>>> that's not desirable.
>>
>> I don't disagree.  I find dconst0 much easier to read than dconst<0> ().
>> In some ways I was posting the patch to show how bad it could be :-)
>>
>> If we're prepared to pay the cost of unconditional load-time
>> initialisation, we could have:
>>
>> template <int N>
>> struct dconst_value
>> {
>>  dconst_value () { ...set up value ...; }
>>  REAL_VALUE_TYPE value;
>> };
>>
>> template <int N>
>> const REAL_VALUE_TYPE &
>> dconst<T> (void)
>> {
>>  static dconst_value<N> x;
>>  return x.value;
>> }
>
> Why are you calling this load-time initialization? As far as I know, such 
> a static object is still initialized lazily (with all the overhead this 
> implies). Did you mean to make value a static member of dconst_value?

Bah, of course, sorry.
Richard Biener Oct. 6, 2015, 8:26 a.m. UTC | #10
On Mon, Oct 5, 2015 at 4:47 PM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> Richard Biener <richard.guenther@gmail.com> writes:
>> On Thu, Oct 1, 2015 at 3:59 PM, Bernd Schmidt <bschmidt@redhat.com> wrote:
>>> On 10/01/2015 03:51 PM, Richard Sandiford wrote:
>>>>
>>>> We have a global 1/2 and a cached 1/3, but recalculate 1/4, 1/6 and 1/9
>>>> each time we need them.  That seems a bit arbitrary and makes the folding
>>>> code more noisy (especially once it's moved to match.pd).
>>>>
>>>> This patch caches the other three constants too.  Bootstrapped &
>>>> regression-tested on x86_64-linux-gnu.  OK to install?
>>>
>>>
>>> Looks reasonable enough.
>>
>> Given
>>
>> /* Returns the special REAL_VALUE_TYPE corresponding to 1/3.  */
>>
>> const REAL_VALUE_TYPE *
>> dconst_third_ptr (void)
>> {
>>   static REAL_VALUE_TYPE value;
>>
>>   /* Initialize mathematical constants for constant folding builtins.
>>      These constants need to be given to at least 160 bits precision.  */
>>   if (value.cl == rvc_zero)
>>     {
>>       real_arithmetic (&value, RDIV_EXPR, &dconst1, real_digit (3));
>>     }
>>   return &value;
>> }
>>
>> I wonder if it makes sense to have
>>
>> template<int a, int b>
>> const REAL_VALUE_TYPE &
>> dconst (void)
>> {
>>   static REAL_VALUE_TYPE value;
>>   if (value.cl == rvc_zero)
>>     real_arithmetic (&value, RDIV_EXPR, real_digit (a), real_digit (b));
>>   return value;
>> }
>>
>> instead which allows us to use
>>
>>   dconst<1,2>()
>>
>> in place of dconst_half () and allows arbitrary extra cached constants to be
>> added (well, double-check that, but I think the function static should be
>> a .comdat).
>
> You suggested on IRC that we do the same for the integral constants,
> so e.g. dconst0 becomes dconst<0> ().  Here's the result.  Like I said,
> I think this may be a case of "be careful what you wish for".
>
> Bootstrapped & regression-tested on x86_64-linux-gnu.  Also tested by
> building one target per CPU directory and checking that there were no
> new warnings and no changes in testsuite output at -O2.  OK to install?

Ok.  Note that if people don't like the dconst<1,2> () syntax we could wrap
it in a macro

#define DCONST(a, args...) dconst<a, #args> ()

and use DCONST(1, 2) (well, if I got the variadic macro syntax right and if
that's a required feature in C++04, it's in C++11 at least).

I wonder if C++23 will finally get sth like Schemes define-syntax ;)

Thanks,
Richard.

> Thanks,
> Richard
>
>
> gcc/ada/
>         * gcc-interface/trans.c (convert_with_check): Use dconst template
>         instead of static variables.
>
> gcc/c-family/
>         * c-common.c (c_common_truthvalue_conversion): Use dconst template
>         instead of static variables.
>         * c-lex.c (interpret_float): Likewise.
>         * c-ubsan.c (ubsan_instrument_division): Likewise.
>
> gcc/java/
>         * decl.c (java_init_decl_processing): Use dconst template instead
>         of static variables.
>
> gcc/
>         * real.h (dconst0, dconst1, dconst2, dconstm1, dconsthalf): Delete.
>         (dconst_third, dconst_third_ptr): Delete.
>         (real_from_fraction): Declare.
>         (dconst): New function.
>         * real.c (real_from_fraction): New function.
>         (real_digit, dconst_third_ptr): Delete.
>         (exact_real_inverse, real_to_decimal_for_mode, decimal_integer_string)
>         (ten_to_mptwo, times_pten): Use dconst instead of real_digit.
>         (real_powi, real_floor, real_ceil, real_round): Use dconst
>         instead of static variables.
>         * emit-rtl.c (dconst0, dconst1, dconst2, dconstm1, dconsthalf): Delete.
>         (init_emit_once): Don't initialize them.
>         * builtins.c (fold_builtin_sqrt, fold_builtin_cbrt): Use dconst
>         instead of static variables.  Also use dconst<1, 6> and dconst<1, 9>
>         instead of deriving them from doncst_third.
>         (expand_builtin_cexpi, expand_builtin_signbit, fold_builtin_cabs)
>         (fold_builtin_pow, fold_builtin_powi, fold_builtin_signbit)
>         (fold_builtin_modf, fold_builtin_classify, fold_builtin_fpclassify)
>         (fold_builtin_1, fold_builtin_2): Use dconst instead of static
>         variables.
>         * doc/match-and-simplify.texi: Likewise (in examples).
>         * config/aarch64/aarch64.c (aarch64_float_const_zero_rtx_p): Likewise.
>         * config/c6x/c6x.md (divsf3, divdf3): Likewise.
>         * config/fr30/fr30.c (fr30_const_double_is_zero): Likewise.
>         * config/i386/i386.c (standard_80387_constant_p): Likewise.
>         (ix86_expand_convert_uns_didf_sse, ix86_expand_convert_uns_sidf_sse)
>         (ix86_expand_convert_sign_didf_sse, ix86_expand_convert_uns_sisf_sse)
>         (ix86_expand_vector_convert_uns_vsivsf): Likewise.
>         (ix86_expand_adjust_ufix_to_sfix_si, ix86_emit_i387_round): Likewise.
>         (ix86_emit_swsqrtsf, ix86_gen_TWO52, ix86_expand_lround): Likewise.
>         (ix86_expand_floorceildf_32, ix86_expand_floorceil): Likewise.
>         (ix86_expand_rounddf_32, ix86_expand_truncdf_32): Likewise.
>         (ix86_expand_round, ix86_expand_round_sse4): Likewise.
>         * config/i386/i386.md (fixuns_trunc<mode>si2): Likewise.
>         * config/i386/sse.md (vec_unpacku_float_hi_v4si): Likewise.
>         (vec_unpacku_float_lo_v4si, vec_unpacku_float_hi_v8si): Likewise.
>         (vec_unpacku_float_hi_v16si, vec_unpacku_float_lo_v8si): Likewise.
>         (vec_unpacku_float_lo_v16si, round<mode>2): Likewise.
>         * config/m68k/m68k.c (floating_exact_log2): Likewise.
>         * config/rs6000/rs6000.c (rs6000_emit_swdiv): Likewise.
>         (rs6000_scale_v2df): Likewise.
>         * config/rs6000/rs6000.md (*cmptf_internal2): Likewise.
>         * config/sh/sh.c (fp_zero_operand, fp_one_operand): Likewise.
>         * config/xtensa/predicates.md (const_float_1_operand): Likewise.
>         * cprop.c (implicit_set_cond_p): Likewise.
>         * dfp.c (decimal_to_decnumber): Likewise.
>         * expmed.c (expand_mult): Likewise.
>         * fold-const.c (const_binop, distribute_real_division): Likewise.
>         (fold_binary_loc): Likewise.
>         * match.pd: Likewise throughout.
>         * simplify-rtx.c (simplify_binary_operation_1): Likewise.
>         (simplify_const_binary_operation): Likewise.
>         * tree-call-cdce.c (check_pow): Likewise.
>         (gen_conditions_for_pow_cst_base): Likewise.
>         * tree-chrec.c (chrec_fold_plus_poly_poly): Likewise.
>         (chrec_fold_multiply_poly_poly, chrec_fold_plus_1): Likewise.
>         * tree-complex.c (some_nonzerop, get_component_ssa_name): Likewise.
>         (expand_complex_multiplication): Likewise.
>         * tree-inline.c (estimate_num_insns): Likewise.
>         * tree-scalar-evolution.c (add_to_evolution_1): Likewise.
>         (add_to_evolution): Likewise.
>         * tree-ssa-dom.c (record_equality): Likewise.
>         * tree-ssa-math-opts.c (powi_as_mults): Likewise.
>         (representable_as_half_series_p, expand_pow_as_sqrts): Likewise.
>         (pass_cse_sincos::execute): Likewise.
>         (pass_optimize_widening_mul::execute): Likewise.
>         (gimple_expand_builtin_pow): Likewise.  Use dconst instead of
>         local variables for 3 and 1/4.
>         * tree-ssa-uncprop.c (associate_equivalences_with_edges): Use dconst
>         instead of static variables.
>         * tree-vect-loop.c (get_initial_def_for_reduction): Likewise.
>         * tree-vect-patterns.c (vect_recog_pow_pattern): Likewise.
>         * tree-vect-slp.c (vect_get_constant_vectors): Likewise.
>         * tree.c (build_one_cst, build_minus_one_cst, build_zero_cst)
>         (real_zerop, real_onep, real_minus_onep): Likewise.
>         * ubsan.c (ubsan_instrument_float_cast): Likewise.
>
> diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
> index f1e2dcb..f00dfee 100644
> --- a/gcc/ada/gcc-interface/trans.c
> +++ b/gcc/ada/gcc-interface/trans.c
> @@ -9048,7 +9048,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
>        /* Compute the exact value calc_type'Pred (0.5) at compile time.  */
>        fmt = REAL_MODE_FORMAT (TYPE_MODE (calc_type));
>        real_2expN (&half_minus_pred_half, -(fmt->p) - 1, TYPE_MODE (calc_type));
> -      real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf,
> +      real_arithmetic (&pred_half, MINUS_EXPR, &dconst<1, 2> (),
>                        &half_minus_pred_half);
>        gnu_pred_half = build_real (calc_type, pred_half);
>
> diff --git a/gcc/builtins.c b/gcc/builtins.c
> index 89bea60..85ba6dd 100644
> --- a/gcc/builtins.c
> +++ b/gcc/builtins.c
> @@ -2659,7 +2659,7 @@ expand_builtin_cexpi (tree exp, rtx target)
>         }
>
>        narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
> -                         build_real (type, dconst0), arg);
> +                         build_real (type, dconst<0> ()), arg);
>
>        /* Make sure not to fold the cexp call again.  */
>        call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
> @@ -4983,7 +4983,7 @@ expand_builtin_signbit (tree exp, rtx target)
>      gcc_assert (!fmt->has_signed_zero || !HONOR_SIGNED_ZEROS (fmode));
>
>      arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
> -                      build_real (TREE_TYPE (arg), dconst0));
> +                      build_real (TREE_TYPE (arg), dconst<0> ()));
>      return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
>    }
>
> @@ -7642,7 +7642,7 @@ fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
>  static tree
>  build_complex_cproj (tree type, bool neg)
>  {
> -  REAL_VALUE_TYPE rinf, rzero = dconst0;
> +  REAL_VALUE_TYPE rinf, rzero = dconst<0> ();
>
>    real_inf (&rinf);
>    rzero.sign = neg;
> @@ -7720,7 +7720,7 @@ fold_builtin_sqrt (location_t loc, tree arg, tree type)
>      return NULL_TREE;
>
>    /* Calculate the result when the argument is a constant.  */
> -  if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
> +  if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst<0> (), NULL, true)))
>      return res;
>
>    /* Optimize sqrt(expN(x)) = expN(x*0.5).  */
> @@ -7730,7 +7730,7 @@ fold_builtin_sqrt (location_t loc, tree arg, tree type)
>        tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
>        arg = fold_build2_loc (loc, MULT_EXPR, type,
>                          CALL_EXPR_ARG (arg, 0),
> -                        build_real (type, dconsthalf));
> +                        build_real (type, dconst<1, 2> ()));
>        return build_call_expr_loc (loc, expfn, 1, arg);
>      }
>
> @@ -7742,20 +7742,10 @@ fold_builtin_sqrt (location_t loc, tree arg, tree type)
>        if (powfn)
>         {
>           tree arg0 = CALL_EXPR_ARG (arg, 0);
> -         tree tree_root;
> -         /* The inner root was either sqrt or cbrt.  */
> -         /* This was a conditional expression but it triggered a bug
> -            in Sun C 5.5.  */
> -         REAL_VALUE_TYPE dconstroot;
> -         if (BUILTIN_SQRT_P (fcode))
> -           dconstroot = dconsthalf;
> -         else
> -           dconstroot = dconst_third ();
> -
> -         /* Adjust for the outer root.  */
> -         SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
> -         tree_root = build_real_truncate (type, dconstroot);
> -         return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
> +         tree arg1 = (BUILTIN_SQRT_P (fcode)
> +                      ? build_real (type, dconst<1, 4> ())
> +                      : build_real_truncate (type, dconst<1, 6> ()));
> +         return build_call_expr_loc (loc, powfn, 2, arg0, arg1);
>         }
>      }
>
> @@ -7772,7 +7762,7 @@ fold_builtin_sqrt (location_t loc, tree arg, tree type)
>        if (!tree_expr_nonnegative_p (arg0))
>         arg0 = build1 (ABS_EXPR, type, arg0);
>        narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
> -                          build_real (type, dconsthalf));
> +                          build_real (type, dconst<1, 2> ()));
>        return build_call_expr_loc (loc, powfn, 2, arg0, narg1);
>      }
>
> @@ -7803,7 +7793,7 @@ fold_builtin_cbrt (location_t loc, tree arg, tree type)
>           tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
>           arg = fold_build2_loc (loc, MULT_EXPR, type,
>                                  CALL_EXPR_ARG (arg, 0),
> -                                build_real_truncate (type, dconst_third ()));
> +                                build_real_truncate (type, dconst<1, 3> ()));
>           return build_call_expr_loc (loc, expfn, 1, arg);
>         }
>
> @@ -7815,11 +7805,7 @@ fold_builtin_cbrt (location_t loc, tree arg, tree type)
>           if (powfn)
>             {
>               tree arg0 = CALL_EXPR_ARG (arg, 0);
> -             tree tree_root;
> -             REAL_VALUE_TYPE dconstroot = dconst_third ();
> -
> -             SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
> -             tree_root = build_real_truncate (type, dconstroot);
> +             tree tree_root = build_real_truncate (type, dconst<1, 6> ());
>               return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
>             }
>         }
> @@ -7834,12 +7820,7 @@ fold_builtin_cbrt (location_t loc, tree arg, tree type)
>
>               if (powfn)
>                 {
> -                 tree tree_root;
> -                 REAL_VALUE_TYPE dconstroot;
> -
> -                 real_arithmetic (&dconstroot, MULT_EXPR,
> -                                   dconst_third_ptr (), dconst_third_ptr ());
> -                 tree_root = build_real_truncate (type, dconstroot);
> +                 tree tree_root = build_real_truncate (type, dconst<1, 9> ());
>                   return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
>                 }
>             }
> @@ -7855,7 +7836,7 @@ fold_builtin_cbrt (location_t loc, tree arg, tree type)
>           if (tree_expr_nonnegative_p (arg00))
>             {
>               tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
> -             tree c = build_real_truncate (type, dconst_third ());
> +             tree c = build_real_truncate (type, dconst<1, 3> ());
>               tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01, c);
>               return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
>             }
> @@ -8407,7 +8388,8 @@ fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
>
>    /* Optimize pow(1.0,y) = 1.0.  */
>    if (real_onep (arg0))
> -    return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
> +    return omit_one_operand_loc (loc, type,
> +                                build_real (type, dconst<1> ()), arg1);
>
>    if (TREE_CODE (arg1) == REAL_CST
>        && !TREE_OVERFLOW (arg1))
> @@ -8419,22 +8401,22 @@ fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
>        c = TREE_REAL_CST (arg1);
>
>        /* Optimize pow(x,0.0) = 1.0.  */
> -      if (real_equal (&c, &dconst0))
> -       return omit_one_operand_loc (loc, type, build_real (type, dconst1),
> -                                arg0);
> +      if (real_equal (&c, &dconst<0> ()))
> +       return omit_one_operand_loc (loc, type,
> +                                    build_real (type, dconst<1> ()), arg0);
>
>        /* Optimize pow(x,1.0) = x.  */
> -      if (real_equal (&c, &dconst1))
> +      if (real_equal (&c, &dconst<1> ()))
>         return arg0;
>
>        /* Optimize pow(x,-1.0) = 1.0/x.  */
> -      if (real_equal (&c, &dconstm1))
> +      if (real_equal (&c, &dconst<-1> ()))
>         return fold_build2_loc (loc, RDIV_EXPR, type,
> -                           build_real (type, dconst1), arg0);
> +                           build_real (type, dconst<1> ()), arg0);
>
>        /* Optimize pow(x,0.5) = sqrt(x).  */
>        if (flag_unsafe_math_optimizations
> -         && real_equal (&c, &dconsthalf))
> +         && real_equal (&c, &dconst<1, 2> ()))
>         {
>           tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
>
> @@ -8446,7 +8428,7 @@ fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
>        if (flag_unsafe_math_optimizations)
>         {
>           const REAL_VALUE_TYPE dconstroot
> -           = real_value_truncate (TYPE_MODE (type), dconst_third ());
> +           = real_value_truncate (TYPE_MODE (type), dconst<1, 3> ());
>
>           if (real_equal (&c, &dconstroot))
>             {
> @@ -8467,7 +8449,7 @@ fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
>               && !TREE_OVERFLOW (arg0)
>               && (n > 0
>                   || (!flag_trapping_math && !flag_errno_math)
> -                 || !real_equal (&TREE_REAL_CST (arg0), &dconst0)))
> +                 || !real_equal (&TREE_REAL_CST (arg0), &dconst<0> ())))
>             {
>               REAL_VALUE_TYPE x;
>               bool inexact;
> @@ -8506,7 +8488,7 @@ fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
>         {
>           tree narg0 = CALL_EXPR_ARG (arg0, 0);
>           tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
> -                                   build_real (type, dconsthalf));
> +                                   build_real (type, dconst<1, 2> ()));
>           return build_call_expr_loc (loc, fndecl, 2, narg0, narg1);
>         }
>
> @@ -8516,7 +8498,7 @@ fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
>           tree arg = CALL_EXPR_ARG (arg0, 0);
>           if (tree_expr_nonnegative_p (arg))
>             {
> -             tree c = build_real_truncate (type, dconst_third ());
> +             tree c = build_real_truncate (type, dconst<1, 3> ());
>               tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1, c);
>               return build_call_expr_loc (loc, fndecl, 2, arg, narg1);
>             }
> @@ -8552,7 +8534,8 @@ fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
>
>    /* Optimize pow(1.0,y) = 1.0.  */
>    if (real_onep (arg0))
> -    return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
> +    return omit_one_operand_loc (loc, type,
> +                                build_real (type, dconst<1> ()), arg1);
>
>    if (tree_fits_shwi_p (arg1))
>      {
> @@ -8570,8 +8553,8 @@ fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
>
>        /* Optimize pow(x,0) = 1.0.  */
>        if (c == 0)
> -       return omit_one_operand_loc (loc, type, build_real (type, dconst1),
> -                                arg0);
> +       return omit_one_operand_loc (loc, type,
> +                                    build_real (type, dconst<1> ()), arg0);
>
>        /* Optimize pow(x,1) = x.  */
>        if (c == 1)
> @@ -8580,7 +8563,7 @@ fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
>        /* Optimize pow(x,-1) = 1.0/x.  */
>        if (c == -1)
>         return fold_build2_loc (loc, RDIV_EXPR, type,
> -                          build_real (type, dconst1), arg0);
> +                               build_real (type, dconst<1> ()), arg0);
>      }
>
>    return NULL_TREE;
> @@ -8922,7 +8905,8 @@ fold_builtin_signbit (location_t loc, tree arg, tree type)
>    if (!HONOR_SIGNED_ZEROS (arg))
>      return fold_convert (type,
>                          fold_build2_loc (loc, LT_EXPR, boolean_type_node, arg,
> -                       build_real (TREE_TYPE (arg), dconst0)));
> +                                         build_real (TREE_TYPE (arg),
> +                                                     dconst<0> ())));
>
>    return NULL_TREE;
>  }
> @@ -9398,7 +9382,7 @@ fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
>         break;
>        case rvc_inf:
>         /* For +-Inf, return (*arg1 = arg0, +-0).  */
> -       frac = dconst0;
> +       frac = dconst<0> ();
>         frac.sign = value->sign;
>         trunc = *value;
>         break;
> @@ -9536,7 +9520,7 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
>         {
>           r = TREE_REAL_CST (arg);
>           if (real_isinf (&r))
> -           return real_compare (GT_EXPR, &r, &dconst0)
> +           return real_compare (GT_EXPR, &r, &dconst<0> ())
>                    ? integer_one_node : integer_minus_one_node;
>           else
>             return integer_zero_node;
> @@ -9651,7 +9635,7 @@ fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
>              (x == 0 ? FP_ZERO : FP_SUBNORMAL))).  */
>
>    tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
> -                    build_real (type, dconst0));
> +                    build_real (type, dconst<0> ()));
>    res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
>                      tmp, fp_zero, fp_subnormal);
>
> @@ -9967,13 +9951,13 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
>      CASE_FLT_FN (BUILT_IN_ASIN):
>        if (validate_arg (arg0, REAL_TYPE))
>         return do_mpfr_arg1 (arg0, type, mpfr_asin,
> -                            &dconstm1, &dconst1, true);
> +                            &dconst<-1> (), &dconst<1> (), true);
>      break;
>
>      CASE_FLT_FN (BUILT_IN_ACOS):
>        if (validate_arg (arg0, REAL_TYPE))
>         return do_mpfr_arg1 (arg0, type, mpfr_acos,
> -                            &dconstm1, &dconst1, true);
> +                            &dconst<-1> (), &dconst<1> (), true);
>      break;
>
>      CASE_FLT_FN (BUILT_IN_ATAN):
> @@ -9989,13 +9973,13 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
>      CASE_FLT_FN (BUILT_IN_ACOSH):
>        if (validate_arg (arg0, REAL_TYPE))
>         return do_mpfr_arg1 (arg0, type, mpfr_acosh,
> -                            &dconst1, NULL, true);
> +                            &dconst<1> (), NULL, true);
>      break;
>
>      CASE_FLT_FN (BUILT_IN_ATANH):
>        if (validate_arg (arg0, REAL_TYPE))
>         return do_mpfr_arg1 (arg0, type, mpfr_atanh,
> -                            &dconstm1, &dconst1, false);
> +                            &dconst<-1> (), &dconst<1> (), false);
>      break;
>
>      CASE_FLT_FN (BUILT_IN_SIN):
> @@ -10062,23 +10046,25 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
>
>      CASE_FLT_FN (BUILT_IN_LOG):
>        if (validate_arg (arg0, REAL_TYPE))
> -        return do_mpfr_arg1 (arg0, type, mpfr_log, &dconst0, NULL, false);
> +       return do_mpfr_arg1 (arg0, type, mpfr_log, &dconst<0> (), NULL, false);
>        break;
>
>      CASE_FLT_FN (BUILT_IN_LOG2):
>        if (validate_arg (arg0, REAL_TYPE))
> -        return do_mpfr_arg1 (arg0, type, mpfr_log2, &dconst0, NULL, false);
> +       return do_mpfr_arg1 (arg0, type, mpfr_log2,
> +                            &dconst<0> (), NULL, false);
>        break;
>
>      CASE_FLT_FN (BUILT_IN_LOG10):
>        if (validate_arg (arg0, REAL_TYPE))
> -        return do_mpfr_arg1 (arg0, type, mpfr_log10, &dconst0, NULL, false);
> +       return do_mpfr_arg1 (arg0, type, mpfr_log10,
> +                            &dconst<0> (), NULL, false);
>        break;
>
>      CASE_FLT_FN (BUILT_IN_LOG1P):
>        if (validate_arg (arg0, REAL_TYPE))
>         return do_mpfr_arg1 (arg0, type, mpfr_log1p,
> -                            &dconstm1, NULL, false);
> +                            &dconst<-1> (), NULL, false);
>      break;
>
>      CASE_FLT_FN (BUILT_IN_J0):
> @@ -10096,13 +10082,13 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
>      CASE_FLT_FN (BUILT_IN_Y0):
>        if (validate_arg (arg0, REAL_TYPE))
>         return do_mpfr_arg1 (arg0, type, mpfr_y0,
> -                            &dconst0, NULL, false);
> +                            &dconst<0> (), NULL, false);
>      break;
>
>      CASE_FLT_FN (BUILT_IN_Y1):
>        if (validate_arg (arg0, REAL_TYPE))
>         return do_mpfr_arg1 (arg0, type, mpfr_y1,
> -                            &dconst0, NULL, false);
> +                            &dconst<0> (), NULL, false);
>      break;
>
>      CASE_FLT_FN (BUILT_IN_NAN):
> @@ -10247,7 +10233,7 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1)
>        if (validate_arg (arg0, INTEGER_TYPE)
>           && validate_arg (arg1, REAL_TYPE))
>         return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
> -                                &dconst0, false);
> +                                &dconst<0> (), false);
>      break;
>
>      CASE_FLT_FN (BUILT_IN_DREM):
> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> index 4b64a44..9d1126b 100644
> --- a/gcc/c-family/c-common.c
> +++ b/gcc/c-family/c-common.c
> @@ -4983,7 +4983,7 @@ c_common_truthvalue_conversion (location_t location, tree expr)
>                                   : truthvalue_true_node;
>
>      case REAL_CST:
> -      return real_compare (NE_EXPR, &TREE_REAL_CST (expr), &dconst0)
> +      return real_compare (NE_EXPR, &TREE_REAL_CST (expr), &dconst<0> ())
>              ? truthvalue_true_node
>              : truthvalue_false_node;
>
> diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
> index c69f4a6..30db6a9 100644
> --- a/gcc/c-family/c-lex.c
> +++ b/gcc/c-family/c-lex.c
> @@ -914,9 +914,9 @@ interpret_float (const cpp_token *token, unsigned int flags,
>         }
>      }
>    /* We also give a warning if the value underflows.  */
> -  else if (real_equal (&real, &dconst0)
> +  else if (real_equal (&real, &dconst<0> ())
>            || (const_type != type
> -              && real_equal (&real_trunc, &dconst0)))
> +              && real_equal (&real_trunc, &dconst<0> ())))
>      {
>        REAL_VALUE_TYPE realvoidmode;
>        int oflow = real_from_string (&realvoidmode, copy);
> @@ -924,7 +924,7 @@ interpret_float (const cpp_token *token, unsigned int flags,
>                               : (oflow < 0 ? OT_UNDERFLOW : OT_OVERFLOW));
>        if (!(flags & CPP_N_USERDEF))
>         {
> -         if (oflow < 0 || !real_equal (&realvoidmode, &dconst0))
> +         if (oflow < 0 || !real_equal (&realvoidmode, &dconst<0> ()))
>             warning (OPT_Woverflow, "floating constant truncated to zero");
>         }
>      }
> diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
> index 672762c..68b76b8 100644
> --- a/gcc/c-family/c-ubsan.c
> +++ b/gcc/c-family/c-ubsan.c
> @@ -65,7 +65,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
>    else if (TREE_CODE (type) == REAL_TYPE
>            && (flag_sanitize & SANITIZE_FLOAT_DIVIDE))
>      t = fold_build2 (EQ_EXPR, boolean_type_node,
> -                    op1, build_real (type, dconst0));
> +                    op1, build_real (type, dconst<0> ()));
>    else
>      return NULL_TREE;
>
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index c9fe368..7fe1831 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -3768,7 +3768,7 @@ aarch64_float_const_zero_rtx_p (rtx x)
>
>    if (REAL_VALUE_MINUS_ZERO (*CONST_DOUBLE_REAL_VALUE (x)))
>      return !HONOR_SIGNED_ZEROS (GET_MODE (x));
> -  return real_equal (CONST_DOUBLE_REAL_VALUE (x), &dconst0);
> +  return real_equal (CONST_DOUBLE_REAL_VALUE (x), &dconst<0> ());
>  }
>
>  /* Return the fixed registers used for condition codes.  */
> diff --git a/gcc/config/c6x/c6x.md b/gcc/config/c6x/c6x.md
> index fa89587..7824cd7 100644
> --- a/gcc/config/c6x/c6x.md
> +++ b/gcc/config/c6x/c6x.md
> @@ -2809,7 +2809,8 @@
>    "TARGET_FP && flag_reciprocal_math"
>  {
>    operands[3] = force_reg (SFmode,
> -                          const_double_from_real_value (dconst2, SFmode));
> +                          const_double_from_real_value (dconst<2> (),
> +                                                        SFmode));
>    operands[4] = gen_reg_rtx (SFmode);
>    operands[5] = gen_reg_rtx (SFmode);
>    operands[6] = gen_reg_rtx (SFmode);
> @@ -2834,7 +2835,8 @@
>    "TARGET_FP && flag_reciprocal_math"
>  {
>    operands[3] = force_reg (DFmode,
> -                          const_double_from_real_value (dconst2, DFmode));
> +                          const_double_from_real_value (dconst<2> (),
> +                                                        DFmode));
>    operands[4] = gen_reg_rtx (DFmode);
>    operands[5] = gen_reg_rtx (DFmode);
>    operands[6] = gen_reg_rtx (DFmode);
> diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c
> index 6afd5d4..20ab6e4 100644
> --- a/gcc/config/fr30/fr30.c
> +++ b/gcc/config/fr30/fr30.c
> @@ -889,7 +889,7 @@ fr30_const_double_is_zero (rtx operand)
>    if (operand == NULL || GET_CODE (operand) != CONST_DOUBLE)
>      return 0;
>
> -  return real_equal (CONST_DOUBLE_REAL_VALUE (operand), &dconst0);
> +  return real_equal (CONST_DOUBLE_REAL_VALUE (operand), &dconst<0> ());
>  }
>
>  /*}}}*/
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index d59b59b..5591f78 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -10511,7 +10511,7 @@ standard_80387_constant_p (rtx x)
>       fldz;fchs or fld1;fchs sequence.  */
>    if (real_isnegzero (r))
>      return 8;
> -  if (real_identical (r, &dconstm1))
> +  if (real_identical (r, &dconst<-1> ()))
>      return 9;
>
>    return 0;
> @@ -20296,8 +20296,8 @@ ix86_expand_convert_uns_didf_sse (rtx target, rtx input)
>
>    /* Subtract off those 0x1.0p52 and 0x1.0p84 biases, to produce values
>       in [0,2**32-1] and [0]+[2**32,2**64-1] respectively.  */
> -  real_ldexp (&bias_lo_rvt, &dconst1, 52);
> -  real_ldexp (&bias_hi_rvt, &dconst1, 84);
> +  real_ldexp (&bias_lo_rvt, &dconst<1> (), 52);
> +  real_ldexp (&bias_hi_rvt, &dconst<1> (), 84);
>    biases = const_double_from_real_value (bias_lo_rvt, DFmode);
>    x = const_double_from_real_value (bias_hi_rvt, DFmode);
>    biases = gen_rtx_CONST_VECTOR (V2DFmode, gen_rtvec (2, biases, x));
> @@ -20339,7 +20339,7 @@ ix86_expand_convert_uns_sidf_sse (rtx target, rtx input)
>    fp = gen_reg_rtx (DFmode);
>    emit_insn (gen_floatsidf2 (fp, x));
>
> -  real_ldexp (&TWO31r, &dconst1, 31);
> +  real_ldexp (&TWO31r, &dconst<1> (), 31);
>    x = const_double_from_real_value (TWO31r, DFmode);
>
>    x = expand_simple_binop (DFmode, PLUS, fp, x, target, 0, OPTAB_DIRECT);
> @@ -20361,7 +20361,7 @@ ix86_expand_convert_sign_didf_sse (rtx target, rtx input)
>
>    emit_insn (gen_floatsidf2 (fp_hi, gen_highpart (SImode, input)));
>
> -  real_ldexp (&TWO32r, &dconst1, 32);
> +  real_ldexp (&TWO32r, &dconst<1> (), 32);
>    x = const_double_from_real_value (TWO32r, DFmode);
>    fp_hi = expand_simple_binop (DFmode, MULT, fp_hi, x, fp_hi, 0, OPTAB_DIRECT);
>
> @@ -20381,7 +20381,7 @@ ix86_expand_convert_uns_sisf_sse (rtx target, rtx input)
>    REAL_VALUE_TYPE ONE16r;
>    rtx fp_hi, fp_lo, int_hi, int_lo, x;
>
> -  real_ldexp (&ONE16r, &dconst1, 16);
> +  real_ldexp (&ONE16r, &dconst<1> (), 16);
>    x = const_double_from_real_value (ONE16r, SFmode);
>    int_lo = expand_simple_binop (SImode, AND, input, GEN_INT(0xffff),
>                                       NULL, 0, OPTAB_DIRECT);
> @@ -20425,7 +20425,7 @@ ix86_expand_vector_convert_uns_vsivsf (rtx target, rtx val)
>    emit_insn (cvt (tmp[3], tmp[1]));
>    tmp[4] = gen_reg_rtx (fltmode);
>    emit_insn (cvt (tmp[4], tmp[2]));
> -  real_ldexp (&TWO16r, &dconst1, 16);
> +  real_ldexp (&TWO16r, &dconst<1> (), 16);
>    tmp[5] = const_double_from_real_value (TWO16r, SFmode);
>    tmp[5] = force_reg (fltmode, ix86_build_const_vector (fltmode, 1, tmp[5]));
>    tmp[6] = expand_simple_binop (fltmode, MULT, tmp[4], tmp[5], NULL_RTX, 1,
> @@ -20454,7 +20454,7 @@ ix86_expand_adjust_ufix_to_sfix_si (rtx val, rtx *xorp)
>
>    for (i = 0; i < 3; i++)
>      tmp[i] = gen_reg_rtx (mode);
> -  real_ldexp (&TWO31r, &dconst1, 31);
> +  real_ldexp (&TWO31r, &dconst<1> (), 31);
>    two31r = const_double_from_real_value (TWO31r, scalarmode);
>    two31r = ix86_build_const_vector (mode, 1, two31r);
>    two31r = force_reg (mode, two31r);
> @@ -47089,7 +47089,7 @@ void ix86_emit_i387_round (rtx op0, rtx op1)
>    e2 = gen_reg_rtx (inmode);
>    res = gen_reg_rtx (outmode);
>
> -  half = const_double_from_real_value (dconsthalf, inmode);
> +  half = const_double_from_real_value (dconst<1, 2> (), inmode);
>
>    /* round(a) = sgn(a) * floor(fabs(a) + 0.5) */
>
> @@ -47223,7 +47223,7 @@ void ix86_emit_swsqrtsf (rtx res, rtx a, machine_mode mode,
>    real_from_integer (&r, VOIDmode, -3, SIGNED);
>    mthree = const_double_from_real_value (r, SFmode);
>
> -  real_arithmetic (&r, NEGATE_EXPR, &dconsthalf, NULL);
> +  real_arithmetic (&r, NEGATE_EXPR, &dconst<1, 2> (), NULL);
>    mhalf = const_double_from_real_value (r, SFmode);
>    unspec = UNSPEC_RSQRT;
>
> @@ -47508,7 +47508,7 @@ ix86_gen_TWO52 (machine_mode mode)
>    REAL_VALUE_TYPE TWO52r;
>    rtx TWO52;
>
> -  real_ldexp (&TWO52r, &dconst1, mode == DFmode ? 52 : 23);
> +  real_ldexp (&TWO52r, &dconst<1> (), mode == DFmode ? 52 : 23);
>    TWO52 = const_double_from_real_value (TWO52r, mode);
>    TWO52 = force_reg (mode, TWO52);
>
> @@ -47532,7 +47532,8 @@ ix86_expand_lround (rtx op0, rtx op1)
>    /* load nextafter (0.5, 0.0) */
>    fmt = REAL_MODE_FORMAT (mode);
>    real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
> -  real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
> +  real_arithmetic (&pred_half, MINUS_EXPR, &dconst<1, 2> (),
> +                  &half_minus_pred_half);
>
>    /* adj = copysign (0.5, op1) */
>    adj = force_reg (mode, const_double_from_real_value (pred_half, mode));
> @@ -47664,7 +47665,8 @@ ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
>    /* generate 1.0 or -1.0 */
>    one = force_reg (mode,
>                    const_double_from_real_value (do_floor
> -                                                ? dconst1 : dconstm1, mode));
> +                                                ? dconst<1> ()
> +                                                : dconst<-1> (), mode));
>
>    /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
>    tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
> @@ -47723,7 +47725,7 @@ ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
>    expand_float (xa, xi, 0);
>
>    /* generate 1.0 */
> -  one = force_reg (mode, const_double_from_real_value (dconst1, mode));
> +  one = force_reg (mode, const_double_from_real_value (dconst<1> (), mode));
>
>    /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
>    tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
> @@ -47788,7 +47790,8 @@ ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
>    dxa = expand_simple_binop (mode, MINUS, xa2, xa, NULL_RTX, 0, OPTAB_DIRECT);
>
>    /* generate 0.5, 1.0 and -0.5 */
> -  half = force_reg (mode, const_double_from_real_value (dconsthalf, mode));
> +  half = force_reg (mode, const_double_from_real_value (dconst<1, 2> (),
> +                                                       mode));
>    one = expand_simple_binop (mode, PLUS, half, half, NULL_RTX, 0, OPTAB_DIRECT);
>    mhalf = expand_simple_binop (mode, MINUS, half, one, NULL_RTX,
>                                0, OPTAB_DIRECT);
> @@ -47898,7 +47901,7 @@ ix86_expand_truncdf_32 (rtx operand0, rtx operand1)
>    emit_move_insn (res, tmp);
>
>    /* generate 1.0 */
> -  one = force_reg (mode, const_double_from_real_value (dconst1, mode));
> +  one = force_reg (mode, const_double_from_real_value (dconst<1> (), mode));
>
>    /* Compensate: res = xa2 - (res > xa ? 1 : 0)  */
>    mask = ix86_expand_sse_compare_mask (UNGT, res, xa, false);
> @@ -47946,7 +47949,8 @@ ix86_expand_round (rtx operand0, rtx operand1)
>    /* load nextafter (0.5, 0.0) */
>    fmt = REAL_MODE_FORMAT (mode);
>    real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
> -  real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
> +  real_arithmetic (&pred_half, MINUS_EXPR, &dconst<1, 2> (),
> +                  &half_minus_pred_half);
>
>    /* xa = xa + 0.5 */
>    half = force_reg (mode, const_double_from_real_value (pred_half, mode));
> @@ -47997,7 +48001,8 @@ ix86_expand_round_sse4 (rtx op0, rtx op1)
>    /* load nextafter (0.5, 0.0) */
>    fmt = REAL_MODE_FORMAT (mode);
>    real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
> -  real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
> +  real_arithmetic (&pred_half, MINUS_EXPR, &dconst<1, 2> (),
> +                  &half_minus_pred_half);
>    half = const_double_from_real_value (pred_half, mode);
>
>    /* e1 = copysign (0.5, op1) */
> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> index 5fcebb5..140bc0f 100644
> --- a/gcc/config/i386/i386.md
> +++ b/gcc/config/i386/i386.md
> @@ -4643,7 +4643,7 @@
>    if (optimize_insn_for_size_p ())
>      FAIL;
>
> -  real_ldexp (&TWO31r, &dconst1, 31);
> +  real_ldexp (&TWO31r, &dconst<1> (), 31);
>    two31 = const_double_from_real_value (TWO31r, mode);
>    two31 = ix86_build_const_vector (vecmode, true, two31);
>    operands[2] = force_reg (vecmode, two31);
> diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
> index 9b7a338..a016b26 100644
> --- a/gcc/config/i386/sse.md
> +++ b/gcc/config/i386/sse.md
> @@ -5432,7 +5432,7 @@
>    rtx x;
>    int i;
>
> -  real_ldexp (&TWO32r, &dconst1, 32);
> +  real_ldexp (&TWO32r, &dconst<1> (), 32);
>    x = const_double_from_real_value (TWO32r, DFmode);
>
>    operands[3] = force_reg (V2DFmode, CONST0_RTX (V2DFmode));
> @@ -5463,7 +5463,7 @@
>    rtx x;
>    int i;
>
> -  real_ldexp (&TWO32r, &dconst1, 32);
> +  real_ldexp (&TWO32r, &dconst<1> (), 32);
>    x = const_double_from_real_value (TWO32r, DFmode);
>
>    operands[3] = force_reg (V2DFmode, CONST0_RTX (V2DFmode));
> @@ -5483,7 +5483,7 @@
>    rtx x, tmp[6];
>    int i;
>
> -  real_ldexp (&TWO32r, &dconst1, 32);
> +  real_ldexp (&TWO32r, &dconst<1> (), 32);
>    x = const_double_from_real_value (TWO32r, DFmode);
>
>    tmp[0] = force_reg (V4DFmode, CONST0_RTX (V4DFmode));
> @@ -5508,7 +5508,7 @@
>    REAL_VALUE_TYPE TWO32r;
>    rtx k, x, tmp[4];
>
> -  real_ldexp (&TWO32r, &dconst1, 32);
> +  real_ldexp (&TWO32r, &dconst<1> (), 32);
>    x = const_double_from_real_value (TWO32r, DFmode);
>
>    tmp[0] = force_reg (V8DFmode, CONST0_RTX (V8DFmode));
> @@ -5534,7 +5534,7 @@
>    rtx x, tmp[5];
>    int i;
>
> -  real_ldexp (&TWO32r, &dconst1, 32);
> +  real_ldexp (&TWO32r, &dconst<1> (), 32);
>    x = const_double_from_real_value (TWO32r, DFmode);
>
>    tmp[0] = force_reg (V4DFmode, CONST0_RTX (V4DFmode));
> @@ -5557,7 +5557,7 @@
>    REAL_VALUE_TYPE TWO32r;
>    rtx k, x, tmp[3];
>
> -  real_ldexp (&TWO32r, &dconst1, 32);
> +  real_ldexp (&TWO32r, &dconst<1> (), 32);
>    x = const_double_from_real_value (TWO32r, DFmode);
>
>    tmp[0] = force_reg (V8DFmode, CONST0_RTX (V8DFmode));
> @@ -14881,7 +14881,8 @@
>    /* load nextafter (0.5, 0.0) */
>    fmt = REAL_MODE_FORMAT (scalar_mode);
>    real_2expN (&half_minus_pred_half, -(fmt->p) - 1, scalar_mode);
> -  real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
> +  real_arithmetic (&pred_half, MINUS_EXPR, &dconst<1, 2> (),
> +                  &half_minus_pred_half);
>    half = const_double_from_real_value (pred_half, scalar_mode);
>
>    vec_half = ix86_build_const_vector (<MODE>mode, true, half);
> diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
> index bfc19f3..e7226ac 100644
> --- a/gcc/config/m68k/m68k.c
> +++ b/gcc/config/m68k/m68k.c
> @@ -4365,7 +4365,7 @@ floating_exact_log2 (rtx x)
>
>    r = CONST_DOUBLE_REAL_VALUE (x);
>
> -  if (real_less (r, &dconst1))
> +  if (real_less (r, &dconst<1> ()))
>      return 0;
>
>    exp = real_exponent (r);
> diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> index c00d730..39a9a75 100644
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -31944,7 +31944,7 @@ rs6000_emit_swdiv (rtx dst, rtx n, rtx d, bool note_p)
>
>    gcc_assert (code != CODE_FOR_nothing);
>
> -  one = rs6000_load_constant_and_splat (mode, dconst1);
> +  one = rs6000_load_constant_and_splat (mode, dconst<1> ());
>
>    /* x0 = 1./d estimate */
>    x0 = gen_reg_rtx (mode);
> @@ -32684,7 +32684,7 @@ rs6000_scale_v2df (rtx tgt, rtx src, int scale)
>    rtvec v = rtvec_alloc (2);
>    rtx elt;
>    rtx scale_vec = gen_reg_rtx (V2DFmode);
> -  (void)real_powi (&r_pow, DFmode, &dconst2, hwi_scale);
> +  (void)real_powi (&r_pow, DFmode, &dconst<2> (), hwi_scale);
>    elt = const_double_from_real_value (r_pow, DFmode);
>    RTVEC_ELT (v, 0) = elt;
>    RTVEC_ELT (v, 1) = elt;
> diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
> index cf40f10..ae4f492 100644
> --- a/gcc/config/rs6000/rs6000.md
> +++ b/gcc/config/rs6000/rs6000.md
> @@ -10578,7 +10578,7 @@
>    operands[14] = force_const_mem (DFmode,
>                                   const_double_from_real_value (rv, DFmode));
>    operands[15] = force_const_mem (DFmode,
> -                                 const_double_from_real_value (dconst0,
> +                                 const_double_from_real_value (dconst<0> (),
>                                                                 DFmode));
>    if (TARGET_TOC)
>      {
> diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
> index 92e9f9f..f7543d1 100644
> --- a/gcc/config/sh/sh.c
> +++ b/gcc/config/sh/sh.c
> @@ -10005,8 +10005,7 @@ fp_zero_operand (rtx op)
>    if (GET_MODE (op) != SFmode)
>      return false;
>
> -  r = CONST_DOUBLE_REAL_VALUE (op);
> -  return real_equal (r, &dconst0) && ! REAL_VALUE_MINUS_ZERO (*r);
> +  return real_equal (r, &dconst<0> ()) && ! REAL_VALUE_MINUS_ZERO (*r);
>  }
>
>  /* Returns true if OP is a floating point value with value 1.0.  */
> @@ -10016,7 +10015,7 @@ fp_one_operand (rtx op)
>    if (GET_MODE (op) != SFmode)
>      return false;
>
> -  return real_equal (CONST_DOUBLE_REAL_VALUE (op), &dconst1);
> +  return real_equal (CONST_DOUBLE_REAL_VALUE (op), &dconst<1> ());
>  }
>
>  /* Return the TLS type for TLS symbols.  */
> diff --git a/gcc/config/xtensa/predicates.md b/gcc/config/xtensa/predicates.md
> index 00f2370..81e5ebe 100644
> --- a/gcc/config/xtensa/predicates.md
> +++ b/gcc/config/xtensa/predicates.md
> @@ -150,7 +150,7 @@
>  (define_predicate "const_float_1_operand"
>    (match_code "const_double")
>  {
> -  return real_equal (CONST_DOUBLE_REAL_VALUE (op), &dconst1);
> +  return real_equal (CONST_DOUBLE_REAL_VALUE (op), &dconst<1> ());
>  })
>
>  (define_predicate "fpmem_offset_operand"
> diff --git a/gcc/cprop.c b/gcc/cprop.c
> index 4cb8586..f983350 100644
> --- a/gcc/cprop.c
> +++ b/gcc/cprop.c
> @@ -1352,7 +1352,7 @@ implicit_set_cond_p (const_rtx cond)
>        /* ??? The complex and vector checks are not implemented yet.  We just
>          always return zero for them.  */
>        if (CONST_DOUBLE_AS_FLOAT_P (cst)
> -         && real_equal (CONST_DOUBLE_REAL_VALUE (cst), &dconst0))
> +         && real_equal (CONST_DOUBLE_REAL_VALUE (cst), &dconst<0> ()))
>         return 0;
>        else
>         return 0;
> diff --git a/gcc/dfp.c b/gcc/dfp.c
> index ceb43d1..6dbdcad 100644
> --- a/gcc/dfp.c
> +++ b/gcc/dfp.c
> @@ -115,22 +115,22 @@ decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn)
>           /* dconst{1,2,m1,half} are used in various places in
>              the middle-end and optimizers, allow them here
>              as an exception by converting them to decimal.  */
> -         if (memcmp (r, &dconst1, sizeof (*r)) == 0)
> +         if (memcmp (r, &dconst<1> (), sizeof (*r)) == 0)
>             {
>               decNumberFromString (dn, "1", &set);
>               break;
>             }
> -         if (memcmp (r, &dconst2, sizeof (*r)) == 0)
> +         if (memcmp (r, &dconst<2> (), sizeof (*r)) == 0)
>             {
>               decNumberFromString (dn, "2", &set);
>               break;
>             }
> -         if (memcmp (r, &dconstm1, sizeof (*r)) == 0)
> +         if (memcmp (r, &dconst<-1> (), sizeof (*r)) == 0)
>             {
>               decNumberFromString (dn, "-1", &set);
>               break;
>             }
> -         if (memcmp (r, &dconsthalf, sizeof (*r)) == 0)
> +         if (memcmp (r, &dconst<1, 2> (), sizeof (*r)) == 0)
>             {
>               decNumberFromString (dn, "0.5", &set);
>               break;
> diff --git a/gcc/doc/match-and-simplify.texi b/gcc/doc/match-and-simplify.texi
> index c5c2b7e..cc1f573 100644
> --- a/gcc/doc/match-and-simplify.texi
> +++ b/gcc/doc/match-and-simplify.texi
> @@ -165,7 +165,7 @@ chain conditions avoiding nesting @code{if}s too much:
>   (switch
>    /* a CMP (-0) -> a CMP 0  */
>    (if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@@1)))
> -   (cmp @@0 @{ build_real (TREE_TYPE (@@1), dconst0); @}))
> +   (cmp @@0 @{ build_real (TREE_TYPE (@@1), dconst<0> ()); @}))
>    /* x != NaN is always true, other ops are always false.  */
>    (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@@1))
>         && ! HONOR_SNANS (@@1))
> @@ -180,7 +180,7 @@ Is equal to
>   (switch
>    /* a CMP (-0) -> a CMP 0  */
>    (if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@@1)))
> -   (cmp @@0 @{ build_real (TREE_TYPE (@@1), dconst0); @})
> +   (cmp @@0 @{ build_real (TREE_TYPE (@@1), dconst<0> ()); @})
>     /* x != NaN is always true, other ops are always false.  */
>     (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@@1))
>          && ! HONOR_SNANS (@@1))
> @@ -310,7 +310,8 @@ be added to a new @code{for}.  For example
>  (define_operator_list POW BUILT_IN_POWF BUILT_IN_POW BUILT_IN_POWL)
>  (simplify
>   (SQRT (POW @@0 @@1))
> - (POW (abs @@0) (mult @@1 @{ built_real (TREE_TYPE (@@1), dconsthalf); @})))
> + (POW (abs @@0) (mult @@1 @{ build_real (TREE_TYPE (@@1),
> +                                      dconst<1, 2> ()); @})))
>  @end smallexample
>
>  is the same as
> @@ -320,7 +321,8 @@ is the same as
>       POW (BUILT_IN_POWF BUILT_IN_POW BUILT_IN_POWL)
>   (simplify
>    (SQRT (POW @@0 @@1))
> -  (POW (abs @@0) (mult @@1 @{ built_real (TREE_TYPE (@@1), dconsthalf); @}))))
> +  (POW (abs @@0) (mult @@1 @{ build_real (TREE_TYPE (@@1),
> +                                       dconst<1, 2> ()); @}))))
>  @end smallexample
>
>  Another building block are @code{with} expressions in the
> diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
> index c418c24..7d1dc5e 100644
> --- a/gcc/emit-rtl.c
> +++ b/gcc/emit-rtl.c
> @@ -104,12 +104,6 @@ rtx const_tiny_rtx[4][(int) MAX_MACHINE_MODE];
>
>  rtx const_true_rtx;
>
> -REAL_VALUE_TYPE dconst0;
> -REAL_VALUE_TYPE dconst1;
> -REAL_VALUE_TYPE dconst2;
> -REAL_VALUE_TYPE dconstm1;
> -REAL_VALUE_TYPE dconsthalf;
> -
>  /* Record fixed-point constant 0 and 1.  */
>  FIXED_VALUE_TYPE fconst0[MAX_FCONST0];
>  FIXED_VALUE_TYPE fconst1[MAX_FCONST1];
> @@ -5878,7 +5872,6 @@ init_emit_once (void)
>  {
>    int i;
>    machine_mode mode;
> -  machine_mode double_mode;
>
>    /* Initialize the CONST_INT, CONST_WIDE_INT, CONST_DOUBLE,
>       CONST_FIXED, and memory attribute hash tables.  */
> @@ -5917,20 +5910,10 @@ init_emit_once (void)
>
>    double_mode = mode_for_size (DOUBLE_TYPE_SIZE, MODE_FLOAT, 0);
>
> -  real_from_integer (&dconst0, double_mode, 0, SIGNED);
> -  real_from_integer (&dconst1, double_mode, 1, SIGNED);
> -  real_from_integer (&dconst2, double_mode, 2, SIGNED);
> -
> -  dconstm1 = dconst1;
> -  dconstm1.sign = 1;
> -
> -  dconsthalf = dconst1;
> -  SET_REAL_EXP (&dconsthalf, REAL_EXP (&dconsthalf) - 1);
> -
>    for (i = 0; i < 3; i++)
>      {
>        const REAL_VALUE_TYPE *const r =
> -       (i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2);
> +       (i == 0 ? &dconst<0> () : i == 1 ? &dconst<1> () : &dconst<2> ());
>
>        for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
>            mode != VOIDmode;
> diff --git a/gcc/expmed.c b/gcc/expmed.c
> index 93cf508..6327993 100644
> --- a/gcc/expmed.c
> +++ b/gcc/expmed.c
> @@ -3235,7 +3235,7 @@ expand_mult (machine_mode mode, rtx op0, rtx op1, rtx target,
>
>    /* Expand x*2.0 as x+x.  */
>    if (CONST_DOUBLE_AS_FLOAT_P (scalar_op1)
> -      && real_equal (CONST_DOUBLE_REAL_VALUE (scalar_op1), &dconst2))
> +      && real_equal (CONST_DOUBLE_REAL_VALUE (scalar_op1), &dconst<2> ()))
>      {
>        op0 = force_reg (GET_MODE (op0), op0);
>        return expand_binop (mode, add_optab, op0, op0,
> diff --git a/gcc/fold-const.c b/gcc/fold-const.c
> index 2851a29..60149c8 100644
> --- a/gcc/fold-const.c
> +++ b/gcc/fold-const.c
> @@ -1176,7 +1176,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
>        /* Don't perform operation if it would raise a division
>          by zero exception.  */
>        if (code == RDIV_EXPR
> -         && real_equal (&d2, &dconst0)
> +         && real_equal (&d2, &dconst<0> ())
>           && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode)))
>         return NULL_TREE;
>
> @@ -3600,9 +3600,9 @@ distribute_real_division (location_t loc, enum tree_code code, tree type,
>        r0 = TREE_REAL_CST (TREE_OPERAND (arg0, 1));
>        r1 = TREE_REAL_CST (TREE_OPERAND (arg1, 1));
>        if (!mul0)
> -       real_arithmetic (&r0, RDIV_EXPR, &dconst1, &r0);
> +       real_arithmetic (&r0, RDIV_EXPR, &dconst<1> (), &r0);
>        if (!mul1)
> -        real_arithmetic (&r1, RDIV_EXPR, &dconst1, &r1);
> +       real_arithmetic (&r1, RDIV_EXPR, &dconst<1> (), &r1);
>        real_arithmetic (&r0, code, &r0, &r1);
>        return fold_build2_loc (loc, MULT_EXPR, type,
>                           TREE_OPERAND (arg0, 0),
> @@ -9914,7 +9914,7 @@ fold_binary_loc (location_t loc,
>
>                   if (powfn)
>                     {
> -                     tree arg = build_real (type, dconst2);
> +                     tree arg = build_real (type, dconst<2> ());
>                       return build_call_expr_loc (loc, powfn, 2, arg0, arg);
>                     }
>                 }
> diff --git a/gcc/java/decl.c b/gcc/java/decl.c
> index c035fe0..6bb3aa1 100644
> --- a/gcc/java/decl.c
> +++ b/gcc/java/decl.c
> @@ -669,8 +669,8 @@ java_init_decl_processing (void)
>                          double_type_node));
>    layout_type (double_type_node);
>
> -  float_zero_node = build_real (float_type_node, dconst0);
> -  double_zero_node = build_real (double_type_node, dconst0);
> +  float_zero_node = build_real (float_type_node, dconst<0> ());
> +  double_zero_node = build_real (double_type_node, dconst<0> ());
>
>    /* These are the vtables for arrays of primitives.  */
>    boolean_array_vtable = create_primitive_vtable ("boolean");
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 9962b0a..8e2069b 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -1298,7 +1298,7 @@ along with GCC; see the file COPYING3.  If not see
>  (simplify
>   (plus @0 @0)
>   (if (SCALAR_FLOAT_TYPE_P (type))
> -  (mult @0 { build_real (type, dconst2); })))
> +  (mult @0 { build_real (type, dconst<2> ()); })))
>
>  (simplify
>   (minus integer_zerop @1)
> @@ -1598,7 +1598,7 @@ along with GCC; see the file COPYING3.  If not see
>    (switch
>     /* a CMP (-0) -> a CMP 0  */
>     (if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@1)))
> -    (cmp @0 { build_real (TREE_TYPE (@1), dconst0); }))
> +    (cmp @0 { build_real (TREE_TYPE (@1), dconst<0> ()); }))
>     /* x != NaN is always true, other ops are always false.  */
>     (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@1))
>         && ! HONOR_SNANS (@1))
> @@ -1694,7 +1694,7 @@ along with GCC; see the file COPYING3.  If not see
>         (if (cmp == NE_EXPR || !HONOR_NANS (@0))
>         { constant_boolean_node (true, type); })
>         /* sqrt(x) > y is the same as x >= 0, if y is negative.  */
> -       (ge @0 { build_real (TREE_TYPE (@0), dconst0); })))
> +       (ge @0 { build_real (TREE_TYPE (@0), dconst<0> ()); })))
>       (if (cmp == GT_EXPR || cmp == GE_EXPR)
>        (with
>         {
> @@ -1731,11 +1731,11 @@ along with GCC; see the file COPYING3.  If not see
>          /* sqrt(x) < y is x >= 0 when y is very large and we
>             don't care about Infinities.  */
>          (if (! HONOR_INFINITIES (@0))
> -         (ge @0 { build_real (TREE_TYPE (@0), dconst0); }))
> +         (ge @0 { build_real (TREE_TYPE (@0), dconst<0> ()); }))
>          /* sqrt(x) < y is x >= 0 && x != +Inf, when y is large.  */
>          (if (GENERIC)
>           (truth_andif
> -          (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
> +          (ge @0 { build_real (TREE_TYPE (@0), dconst<0> ()); })
>            (ne @0 { build_real (TREE_TYPE (@0), c2); }))))
>         /* sqrt(x) < c is the same as x < c*c, if we ignore NaNs.  */
>         (if (! HONOR_NANS (@0))
> @@ -1743,7 +1743,7 @@ along with GCC; see the file COPYING3.  If not see
>          /* sqrt(x) < c is the same as x >= 0 && x < c*c.  */
>          (if (GENERIC)
>           (truth_andif
> -          (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
> +          (ge @0 { build_real (TREE_TYPE (@0), dconst<0> ()); })
>            (cmp @0 { build_real (TREE_TYPE (@0), c2); }))))))))))))
>
>  /* Unordered tests if either argument is a NaN.  */
> @@ -2193,7 +2193,7 @@ along with GCC; see the file COPYING3.  If not see
>           break;
>         CASE_FLT_FN (BUILT_IN_EXP2):
>           /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
> -         x = build_real (type, dconst2);
> +         x = build_real (type, dconst<2> ());
>           break;
>         CASE_FLT_FN (BUILT_IN_EXP10):
>         CASE_FLT_FN (BUILT_IN_POW10):
> @@ -2221,11 +2221,11 @@ along with GCC; see the file COPYING3.  If not see
>         {
>         CASE_FLT_FN (BUILT_IN_SQRT):
>          /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
> -        x = build_real (type, dconsthalf);
> +        x = build_real (type, dconst<1, 2> ());
>           break;
>         CASE_FLT_FN (BUILT_IN_CBRT):
>          /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
> -         x = build_real_truncate (type, dconst_third ());
> +        x = build_real_truncate (type, dconst<1, 3> ());
>           break;
>         default:
>          gcc_unreachable ();
> diff --git a/gcc/real.c b/gcc/real.c
> index 49d6739..fb77502 100644
> --- a/gcc/real.c
> +++ b/gcc/real.c
> @@ -111,7 +111,6 @@ static void decimal_integer_string (char *, const REAL_VALUE_TYPE *,
>
>  static const REAL_VALUE_TYPE * ten_to_ptwo (int);
>  static const REAL_VALUE_TYPE * ten_to_mptwo (int);
> -static const REAL_VALUE_TYPE * real_digit (int);
>  static void times_pten (REAL_VALUE_TYPE *, int);
>
>  static void round_for_format (const struct real_format *, REAL_VALUE_TYPE *);
> @@ -1273,7 +1272,7 @@ real_identical (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b)
>  bool
>  exact_real_inverse (machine_mode mode, REAL_VALUE_TYPE *r)
>  {
> -  const REAL_VALUE_TYPE *one = real_digit (1);
> +  const REAL_VALUE_TYPE *one = &dconst<1> ();
>    REAL_VALUE_TYPE u;
>    int i;
>
> @@ -1579,7 +1578,7 @@ real_to_decimal_for_mode (char *str, const REAL_VALUE_TYPE *r_orig,
>    if (digits > max_digits)
>      digits = max_digits;
>
> -  one = real_digit (1);
> +  one = &dconst<1> ();
>    ten = ten_to_ptwo (0);
>
>    sign = r.sign;
> @@ -2225,6 +2224,22 @@ real_from_integer (REAL_VALUE_TYPE *r, machine_mode mode,
>      real_convert (r, mode, r);
>  }
>
> +/* Set VALUE to A/B, in maximum precision.  */
> +
> +void
> +real_from_fraction (REAL_VALUE_TYPE *value, int a, int b)
> +{
> +  if (b == 1)
> +    real_from_integer (value, VOIDmode, a, SIGNED);
> +  else
> +    {
> +      REAL_VALUE_TYPE areal, breal;
> +      real_from_integer (&areal, VOIDmode, a, SIGNED);
> +      real_from_integer (&breal, VOIDmode, b, SIGNED);
> +      real_arithmetic (value, RDIV_EXPR, &areal, &breal);
> +    }
> +}
> +
>  /* Render R, an integral value, as a floating point constant with no
>     specified exponent.  */
>
> @@ -2252,7 +2267,7 @@ decimal_integer_string (char *str, const REAL_VALUE_TYPE *r_orig,
>    digits = dec_exp + 1;
>    gcc_assert ((digits + 2) < (int)buf_size);
>
> -  pten = *real_digit (1);
> +  pten = dconst<1> ();
>    times_pten (&pten, dec_exp);
>
>    p = str;
> @@ -2326,27 +2341,11 @@ ten_to_mptwo (int n)
>    gcc_assert (n < EXP_BITS);
>
>    if (tens[n].cl == rvc_zero)
> -    do_divide (&tens[n], real_digit (1), ten_to_ptwo (n));
> +    do_divide (&tens[n], &dconst<1> (), ten_to_ptwo (n));
>
>    return &tens[n];
>  }
>
> -/* Returns N.  */
> -
> -static const REAL_VALUE_TYPE *
> -real_digit (int n)
> -{
> -  static REAL_VALUE_TYPE num[10];
> -
> -  gcc_assert (n >= 0);
> -  gcc_assert (n <= 9);
> -
> -  if (n > 0 && num[n].cl == rvc_zero)
> -    real_from_integer (&num[n], VOIDmode, n, UNSIGNED);
> -
> -  return &num[n];
> -}
> -
>  /* Multiply R by 10**EXP.  */
>
>  static void
> @@ -2359,7 +2358,7 @@ times_pten (REAL_VALUE_TYPE *r, int exp)
>    if (negative)
>      {
>        exp = -exp;
> -      pten = *real_digit (1);
> +      pten = dconst<1> ();
>        rr = &pten;
>      }
>    else
> @@ -2395,22 +2394,6 @@ dconst_e_ptr (void)
>    return &value;
>  }
>
> -/* Returns the special REAL_VALUE_TYPE corresponding to 1/3.  */
> -
> -const REAL_VALUE_TYPE *
> -dconst_third_ptr (void)
> -{
> -  static REAL_VALUE_TYPE value;
> -
> -  /* Initialize mathematical constants for constant folding builtins.
> -     These constants need to be given to at least 160 bits precision.  */
> -  if (value.cl == rvc_zero)
> -    {
> -      real_arithmetic (&value, RDIV_EXPR, &dconst1, real_digit (3));
> -    }
> -  return &value;
> -}
> -
>  /* Returns the special REAL_VALUE_TYPE corresponding to sqrt(2).  */
>
>  const REAL_VALUE_TYPE *
> @@ -4878,7 +4861,7 @@ real_powi (REAL_VALUE_TYPE *r, machine_mode mode,
>
>    if (n == 0)
>      {
> -      *r = dconst1;
> +      *r = dconst<1> ();
>        return false;
>      }
>    else if (n < 0)
> @@ -4906,7 +4889,7 @@ real_powi (REAL_VALUE_TYPE *r, machine_mode mode,
>      }
>
>    if (neg)
> -    inexact |= do_divide (&t, &dconst1, &t);
> +    inexact |= do_divide (&t, &dconst<1> (), &t);
>
>    real_convert (r, mode, &t);
>    return inexact;
> @@ -4935,7 +4918,7 @@ real_floor (REAL_VALUE_TYPE *r, machine_mode mode,
>
>    do_fix_trunc (&t, x);
>    if (! real_identical (&t, x) && x->sign)
> -    do_add (&t, &t, &dconstm1, 0);
> +    do_add (&t, &t, &dconst<-1> (), 0);
>    if (mode != VOIDmode)
>      real_convert (r, mode, &t);
>    else
> @@ -4953,7 +4936,7 @@ real_ceil (REAL_VALUE_TYPE *r, machine_mode mode,
>
>    do_fix_trunc (&t, x);
>    if (! real_identical (&t, x) && ! x->sign)
> -    do_add (&t, &t, &dconst1, 0);
> +    do_add (&t, &t, &dconst<1> (), 0);
>    if (mode != VOIDmode)
>      real_convert (r, mode, &t);
>    else
> @@ -4967,7 +4950,7 @@ void
>  real_round (REAL_VALUE_TYPE *r, machine_mode mode,
>             const REAL_VALUE_TYPE *x)
>  {
> -  do_add (r, x, &dconsthalf, x->sign);
> +  do_add (r, x, &dconst<1, 2> (), x->sign);
>    do_fix_trunc (r, r);
>    if (mode != VOIDmode)
>      real_convert (r, mode, r);
> diff --git a/gcc/real.h b/gcc/real.h
> index 1497279..72e1a04 100644
> --- a/gcc/real.h
> +++ b/gcc/real.h
> @@ -403,22 +403,12 @@ extern void real_ldexp (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int);
>
>  /* Constant real values 0, 1, 2, -1 and 0.5.  */
>
> -extern REAL_VALUE_TYPE dconst0;
> -extern REAL_VALUE_TYPE dconst1;
> -extern REAL_VALUE_TYPE dconst2;
> -extern REAL_VALUE_TYPE dconstm1;
> -extern REAL_VALUE_TYPE dconsthalf;
> -
> -#define dconst_e()  (*dconst_e_ptr ())
> -#define dconst_third()  (*dconst_third_ptr ())
> -#define dconst_sqrt2()  (*dconst_sqrt2_ptr ())
> +#define dconst_e() (*dconst_e_ptr ())
> +#define dconst_sqrt2() (*dconst_sqrt2_ptr ())
>
>  /* Function to return the real value special constant 'e'.  */
>  extern const REAL_VALUE_TYPE * dconst_e_ptr (void);
>
> -/* Returns the special REAL_VALUE_TYPE corresponding to 1/3.  */
> -extern const REAL_VALUE_TYPE * dconst_third_ptr (void);
> -
>  /* Returns the special REAL_VALUE_TYPE corresponding to sqrt(2).  */
>  extern const REAL_VALUE_TYPE * dconst_sqrt2_ptr (void);
>
> @@ -473,6 +463,26 @@ extern void get_max_float (const struct real_format *, char *, size_t);
>  extern wide_int real_to_integer (const REAL_VALUE_TYPE *, bool *, int);
>  extern void real_from_integer (REAL_VALUE_TYPE *, machine_mode,
>                                const wide_int_ref &, signop);
> +extern void real_from_fraction (REAL_VALUE_TYPE *, int, int);
> +
> +/* Return a constant A/B, in maximum precision.  */
> +template<int a, int b>
> +inline const REAL_VALUE_TYPE &
> +dconst (void)
> +{
> +  static REAL_VALUE_TYPE value;
> +  if (value.cl == rvc_zero)
> +    real_from_fraction (&value, a, b);
> +  return value;
> +}
> +
> +/* Return a real for integer constant A.  */
> +template<int a>
> +inline const REAL_VALUE_TYPE &
> +dconst (void)
> +{
> +  return dconst<a, 1> ();
> +}
>  #endif
>
>  #endif /* ! GCC_REAL_H */
> diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
> index 1f91afc..2e0afdd 100644
> --- a/gcc/simplify-rtx.c
> +++ b/gcc/simplify-rtx.c
> @@ -2464,11 +2464,11 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
>         {
>           const REAL_VALUE_TYPE *d1 = CONST_DOUBLE_REAL_VALUE (trueop1);
>
> -         if (real_equal (d1, &dconst2))
> +         if (real_equal (d1, &dconst<2> ()))
>             return simplify_gen_binary (PLUS, mode, op0, copy_rtx (op0));
>
>           if (!HONOR_SNANS (mode)
> -             && real_equal (d1, &dconstm1))
> +             && real_equal (d1, &dconst<-1> ()))
>             return simplify_gen_unary (NEG, mode, op0, mode);
>         }
>
> @@ -3093,17 +3093,17 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
>               const REAL_VALUE_TYPE *d1 = CONST_DOUBLE_REAL_VALUE (trueop1);
>
>               /* x/-1.0 is -x.  */
> -             if (real_equal (d1, &dconstm1)
> +             if (real_equal (d1, &dconst<-1> ())
>                   && !HONOR_SNANS (mode))
>                 return simplify_gen_unary (NEG, mode, op0, mode);
>
>               /* Change FP division by a constant into multiplication.
>                  Only do this with -freciprocal-math.  */
>               if (flag_reciprocal_math
> -                 && !real_equal (d1, &dconst0))
> +                 && !real_equal (d1, &dconst<0> ()))
>                 {
>                   REAL_VALUE_TYPE d;
> -                 real_arithmetic (&d, RDIV_EXPR, &dconst1, d1);
> +                 real_arithmetic (&d, RDIV_EXPR, &dconst<1> (), d1);
>                   tem = const_double_from_real_value (d, mode);
>                   return simplify_gen_binary (MULT, mode, op0, tem);
>                 }
> @@ -3862,7 +3862,7 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
>             return 0;
>
>           if (code == DIV
> -             && real_equal (&f1, &dconst0)
> +             && real_equal (&f1, &dconst<0> ())
>               && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode)))
>             return 0;
>
> @@ -3895,9 +3895,9 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
>
>           if (code == MULT && MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode)
>               && flag_trapping_math
> -             && ((REAL_VALUE_ISINF (f0) && real_equal (&f1, &dconst0))
> +             && ((REAL_VALUE_ISINF (f0) && real_equal (&f1, &dconst<0> ()))
>                   || (REAL_VALUE_ISINF (f1)
> -                     && real_equal (&f0, &dconst0))))
> +                     && real_equal (&f0, &dconst<0> ()))))
>             /* Inf * 0 = NaN plus exception.  */
>             return 0;
>
> diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c
> index 112a325..640e7e5 100644
> --- a/gcc/tree-call-cdce.c
> +++ b/gcc/tree-call-cdce.c
> @@ -199,9 +199,9 @@ check_pow (gcall *pow_call)
>        /* Only handle a fixed range of constant.  */
>        REAL_VALUE_TYPE mv;
>        REAL_VALUE_TYPE bcv = TREE_REAL_CST (base);
> -      if (real_equal (&bcv, &dconst1))
> +      if (real_equal (&bcv, &dconst<1> ()))
>          return false;
> -      if (real_less (&bcv, &dconst1))
> +      if (real_less (&bcv, &dconst<1> ()))
>          return false;
>        real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, UNSIGNED);
>        if (real_less (&mv, &bcv))
> @@ -420,8 +420,8 @@ gen_conditions_for_pow_cst_base (tree base, tree expn,
>       sure it is consistent with check_pow.  */
>    REAL_VALUE_TYPE mv;
>    REAL_VALUE_TYPE bcv = TREE_REAL_CST (base);
> -  gcc_assert (!real_equal (&bcv, &dconst1)
> -              && !real_less (&bcv, &dconst1));
> +  gcc_assert (!real_equal (&bcv, &dconst<1> ())
> +             && !real_less (&bcv, &dconst<1> ()));
>    real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, UNSIGNED);
>    gcc_assert (!real_less (&mv, &bcv));
>
> diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c
> index 649c9fe..4a67eb5 100644
> --- a/gcc/tree-chrec.c
> +++ b/gcc/tree-chrec.c
> @@ -132,7 +132,7 @@ chrec_fold_plus_poly_poly (enum tree_code code,
>            chrec_fold_minus (type, poly0, CHREC_LEFT (poly1)),
>            chrec_fold_multiply (type, CHREC_RIGHT (poly1),
>                                 SCALAR_FLOAT_TYPE_P (type)
> -                               ? build_real (type, dconstm1)
> +                               ? build_real (type, dconst<-1> ())
>                                 : build_int_cst_type (type, -1)));
>      }
>
> @@ -233,7 +233,7 @@ chrec_fold_multiply_poly_poly (tree type,
>    t1 = chrec_fold_plus (type, t1, t2);
>    /* "2*b*d".  */
>    t2 = chrec_fold_multiply (type, SCALAR_FLOAT_TYPE_P (type)
> -                           ? build_real (type, dconst2)
> +                           ? build_real (type, dconst<2> ())
>                             : build_int_cst (type, 2), t2);
>
>    var = CHREC_VARIABLE (poly0);
> @@ -326,7 +326,7 @@ chrec_fold_plus_1 (enum tree_code code, tree type,
>                chrec_fold_minus (type, op0, CHREC_LEFT (op1)),
>                chrec_fold_multiply (type, CHREC_RIGHT (op1),
>                                     SCALAR_FLOAT_TYPE_P (type)
> -                                   ? build_real (type, dconstm1)
> +                                   ? build_real (type, dconst<-1> ())
>                                     : build_int_cst_type (type, -1)));
>
>         CASE_CONVERT:
> diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
> index 93c0a54..2dce4dc 100644
> --- a/gcc/tree-complex.c
> +++ b/gcc/tree-complex.c
> @@ -118,7 +118,7 @@ some_nonzerop (tree t)
>       cannot be treated the same as operations with a real or imaginary
>       operand if we care about the signs of zeros in the result.  */
>    if (TREE_CODE (t) == REAL_CST && !flag_signed_zeros)
> -    zerop = real_identical (&TREE_REAL_CST (t), &dconst0);
> +    zerop = real_identical (&TREE_REAL_CST (t), &dconst<0> ());
>    else if (TREE_CODE (t) == FIXED_CST)
>      zerop = fixed_zerop (t);
>    else if (TREE_CODE (t) == INTEGER_CST)
> @@ -495,7 +495,7 @@ get_component_ssa_name (tree ssa_name, bool imag_p)
>      {
>        tree inner_type = TREE_TYPE (TREE_TYPE (ssa_name));
>        if (SCALAR_FLOAT_TYPE_P (inner_type))
> -       return build_real (inner_type, dconst0);
> +       return build_real (inner_type, dconst<0> ());
>        else
>         return build_int_cst (inner_type, 0);
>      }
> @@ -1021,7 +1021,7 @@ expand_complex_multiplication (gimple_stmt_iterator *gsi, tree inner_type,
>      case PAIR (ONLY_IMAG, ONLY_REAL):
>        rr = ar;
>        if (TREE_CODE (ai) == REAL_CST
> -         && real_identical (&TREE_REAL_CST (ai), &dconst1))
> +         && real_identical (&TREE_REAL_CST (ai), &dconst<1> ()))
>         ri = br;
>        else
>         ri = gimplify_build2 (gsi, MULT_EXPR, inner_type, ai, br);
> diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> index 9b525f3..0758895 100644
> --- a/gcc/tree-inline.c
> +++ b/gcc/tree-inline.c
> @@ -4094,7 +4094,7 @@ estimate_num_insns (gimple *stmt, eni_weights *weights)
>                       if (TREE_CODE (gimple_call_arg (stmt, 1)) == REAL_CST
>                           && (real_equal
>                               (&TREE_REAL_CST (gimple_call_arg (stmt, 1)),
> -                              &dconst2)))
> +                              &dconst<2> ())))
>                         return estimate_operator_cost
>                             (MULT_EXPR, weights, gimple_call_arg (stmt, 0),
>                              gimple_call_arg (stmt, 0));
> diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
> index 0753bf3..e3f94fa 100644
> --- a/gcc/tree-scalar-evolution.c
> +++ b/gcc/tree-scalar-evolution.c
> @@ -638,7 +638,7 @@ add_to_evolution_1 (unsigned loop_nb, tree chrec_before, tree to_add,
>               var = loop_nb;
>               left = chrec_before;
>               right = SCALAR_FLOAT_TYPE_P (type)
> -               ? build_real (type, dconst0)
> +               ? build_real (type, dconst<0> ())
>                 : build_int_cst (type, 0);
>             }
>           else
> @@ -840,7 +840,7 @@ add_to_evolution (unsigned loop_nb, tree chrec_before, enum tree_code code,
>
>    if (code == MINUS_EXPR)
>      to_add = chrec_fold_multiply (type, to_add, SCALAR_FLOAT_TYPE_P (type)
> -                                 ? build_real (type, dconstm1)
> +                                 ? build_real (type, dconst<-1> ())
>                                   : build_int_cst_type (type, -1));
>
>    res = add_to_evolution_1 (loop_nb, chrec_before, to_add, at_stmt);
> diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
> index c226da5..5919c84 100644
> --- a/gcc/tree-ssa-dom.c
> +++ b/gcc/tree-ssa-dom.c
> @@ -1158,7 +1158,7 @@ record_equality (tree x, tree y, class const_and_copies *const_and_copies)
>       nonzero.  */
>    if (HONOR_SIGNED_ZEROS (x)
>        && (TREE_CODE (y) != REAL_CST
> -         || real_equal (&dconst0, &TREE_REAL_CST (y))))
> +         || real_equal (&dconst<0> (), &TREE_REAL_CST (y))))
>      return;
>
>    const_and_copies->record_const_or_copy (x, y, prev_x);
> diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
> index 39c027c..288daef 100644
> --- a/gcc/tree-ssa-math-opts.c
> +++ b/gcc/tree-ssa-math-opts.c
> @@ -1003,7 +1003,7 @@ powi_as_mults (gimple_stmt_iterator *gsi, location_t loc,
>    tree target;
>
>    if (n == 0)
> -    return build_real (type, dconst1);
> +    return build_real (type, dconst<1> ());
>
>    memset (cache, 0,  sizeof (cache));
>    cache[1] = arg0;
> @@ -1015,7 +1015,7 @@ powi_as_mults (gimple_stmt_iterator *gsi, location_t loc,
>    /* If the original exponent was negative, reciprocate the result.  */
>    target = make_temp_ssa_name (type, NULL, "powmult");
>    div_stmt = gimple_build_assign (target, RDIV_EXPR,
> -                                 build_real (type, dconst1), result);
> +                                 build_real (type, dconst<1> ()), result);
>    gimple_set_location (div_stmt, loc);
>    gsi_insert_before (gsi, div_stmt, GSI_SAME_STMT);
>
> @@ -1128,7 +1128,7 @@ bool
>  representable_as_half_series_p (REAL_VALUE_TYPE c, unsigned n,
>                                  struct pow_synth_sqrt_info *info)
>  {
> -  REAL_VALUE_TYPE factor = dconsthalf;
> +  REAL_VALUE_TYPE factor = dconst<1, 2> ();
>    REAL_VALUE_TYPE remainder = c;
>
>    info->deepest = 0;
> @@ -1145,7 +1145,7 @@ representable_as_half_series_p (REAL_VALUE_TYPE c, unsigned n,
>
>        /* We have hit zero.  The number is representable as a sum
>           of powers of 0.5.  */
> -      if (real_equal (&res, &dconst0))
> +      if (real_equal (&res, &dconst<0> ()))
>         {
>           info->factors[i] = true;
>           info->deepest = i + 1;
> @@ -1160,7 +1160,7 @@ representable_as_half_series_p (REAL_VALUE_TYPE c, unsigned n,
>        else
>         info->factors[i] = false;
>
> -      real_arithmetic (&factor, MULT_EXPR, &factor, &dconsthalf);
> +      real_arithmetic (&factor, MULT_EXPR, &factor, &dconst<1, 2> ());
>      }
>    return false;
>  }
> @@ -1320,8 +1320,8 @@ expand_pow_as_sqrts (gimple_stmt_iterator *gsi, location_t loc,
>    real_arithmetic (&frac_part, MINUS_EXPR, &exp, &whole_part);
>
>
> -  REAL_VALUE_TYPE ceil_whole = dconst0;
> -  REAL_VALUE_TYPE ceil_fract = dconst0;
> +  REAL_VALUE_TYPE ceil_whole = dconst<0> ();
> +  REAL_VALUE_TYPE ceil_fract = dconst<0> ();
>
>    if (neg_exp)
>      {
> @@ -1367,7 +1367,7 @@ expand_pow_as_sqrts (gimple_stmt_iterator *gsi, location_t loc,
>
>    memset (cache, 0, (max_depth + 1) * sizeof (tree));
>
> -  tree integer_res = n == 0 ? build_real (type, dconst1) : arg0;
> +  tree integer_res = n == 0 ? build_real (type, dconst<1> ()) : arg0;
>
>    /* Calculate the integer part of the exponent.  */
>    if (n > 1)
> @@ -1447,7 +1447,7 @@ expand_pow_as_sqrts (gimple_stmt_iterator *gsi, location_t loc,
>             res = fract_res;
>
>           res = build_and_insert_binop (gsi, loc, "powrootrecip", RDIV_EXPR,
> -                                         build_real (type, dconst1), res);
> +                                       build_real (type, dconst<1> ()), res);
>         }
>        else
>         {
> @@ -1470,17 +1470,13 @@ static tree
>  gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
>                            tree arg0, tree arg1)
>  {
> -  REAL_VALUE_TYPE c, cint, dconst1_3, dconst1_4, dconst1_6;
> -  REAL_VALUE_TYPE c2, dconst3;
> +  REAL_VALUE_TYPE c, c2, cint, dconst1_3, dconst1_6;
>    HOST_WIDE_INT n;
>    tree type, sqrtfn, cbrtfn, sqrt_arg0, result, cbrt_x, powi_cbrt_x;
>    machine_mode mode;
>    bool speed_p = optimize_bb_for_speed_p (gsi_bb (*gsi));
>    bool hw_sqrt_exists, c_is_int, c2_is_int;
>
> -  dconst1_4 = dconst1;
> -  SET_REAL_EXP (&dconst1_4, REAL_EXP (&dconst1_4) - 2);
> -
>    /* If the exponent isn't a constant, there's nothing of interest
>       to be done.  */
>    if (TREE_CODE (arg1) != REAL_CST)
> @@ -1509,7 +1505,7 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
>       unless signed zeros must be maintained.  pow(-0,0.5) = +0, while
>       sqrt(-0) = -0.  */
>    if (sqrtfn
> -      && real_equal (&c, &dconsthalf)
> +      && real_equal (&c, &dconst<1, 2> ())
>        && !HONOR_SIGNED_ZEROS (mode))
>      return build_and_insert_call (gsi, loc, sqrtfn, arg0);
>
> @@ -1522,7 +1518,7 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
>       of 1./3. actually has an even denominator.  The correct value
>       of cbrt(x) is a negative real value.  */
>    cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
> -  dconst1_3 = real_value_truncate (mode, dconst_third ());
> +  dconst1_3 = real_value_truncate (mode, dconst<1, 3> ());
>
>    if (flag_unsafe_math_optimizations
>        && cbrtfn
> @@ -1556,7 +1552,7 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
>    if (flag_unsafe_math_optimizations
>        && sqrtfn
>        && hw_sqrt_exists
> -      && (speed_p || real_equal (&c, &dconst1_4))
> +      && (speed_p || real_equal (&c, &dconst<1, 4> ()))
>        && !HONOR_SIGNED_ZEROS (mode))
>      {
>        unsigned int max_depth = speed_p
> @@ -1570,7 +1566,7 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
>         return expand_with_sqrts;
>      }
>
> -  real_arithmetic (&c2, MULT_EXPR, &c, &dconst2);
> +  real_arithmetic (&c2, MULT_EXPR, &c, &dconst<2> ());
>    n = real_to_integer (&c2);
>    real_from_integer (&cint, VOIDmode, n, SIGNED);
>    c2_is_int = real_identical (&c2, &cint);
> @@ -1584,12 +1580,11 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
>       different from pow(x, 1./3.) due to rounding and behavior with
>       negative x, we need to constrain this transformation to unsafe
>       math and positive x or finite math.  */
> -  real_from_integer (&dconst3, VOIDmode, 3, SIGNED);
> -  real_arithmetic (&c2, MULT_EXPR, &c, &dconst3);
> +  real_arithmetic (&c2, MULT_EXPR, &c, &dconst<3> ());
>    real_round (&c2, mode, &c2);
>    n = real_to_integer (&c2);
>    real_from_integer (&cint, VOIDmode, n, SIGNED);
> -  real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst3);
> +  real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst<3> ());
>    real_convert (&c2, mode, &c2);
>
>    if (flag_unsafe_math_optimizations
> @@ -1634,7 +1629,8 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
>        /* If n is negative, reciprocate the result.  */
>        if (n < 0)
>         result = build_and_insert_binop (gsi, loc, "powroot", RDIV_EXPR,
> -                                        build_real (type, dconst1), result);
> +                                        build_real (type, dconst<1> ()),
> +                                        result);
>
>        return result;
>      }
> @@ -1793,8 +1789,8 @@ pass_cse_sincos::execute (function *fun)
>
>                       t0 = TREE_TYPE (arg0);
>                       t1 = TREE_TYPE (arg1);
> -                     one = build_real (t0, dconst1);
> -                     minus_one = build_real (t0, dconstm1);
> +                     one = build_real (t0, dconst<1> ());
> +                     minus_one = build_real (t0, dconst<-1> ());
>
>                       cond = make_temp_ssa_name (t1, NULL, "powi_cond");
>                       stmt = gimple_build_assign (cond, BIT_AND_EXPR,
> @@ -3591,7 +3587,7 @@ pass_optimize_widening_mul::execute (function *fun)
>                         if (TREE_CODE (gimple_call_arg (stmt, 1)) == REAL_CST
>                             && real_equal
>                                  (&TREE_REAL_CST (gimple_call_arg (stmt, 1)),
> -                                 &dconst2)
> +                                 &dconst<2> ())
>                             && convert_mult_to_fma (stmt,
>                                                     gimple_call_arg (stmt, 0),
>                                                     gimple_call_arg (stmt, 0)))
> diff --git a/gcc/tree-ssa-uncprop.c b/gcc/tree-ssa-uncprop.c
> index 0f16c50..c247db7 100644
> --- a/gcc/tree-ssa-uncprop.c
> +++ b/gcc/tree-ssa-uncprop.c
> @@ -153,7 +153,7 @@ associate_equivalences_with_edges (void)
>                      this value unless we know that the value is nonzero.  */
>                   if (HONOR_SIGNED_ZEROS (op0)
>                       && (TREE_CODE (op1) != REAL_CST
> -                         || real_equal (&dconst0, &TREE_REAL_CST (op1))))
> +                         || real_equal (&dconst<0> (), &TREE_REAL_CST (op1))))
>                     continue;
>
>                   equivalency = XNEW (struct edge_equivalency);
> diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
> index 63e29aa..7d23428 100644
> --- a/gcc/tree-vect-loop.c
> +++ b/gcc/tree-vect-loop.c
> @@ -3821,7 +3821,7 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
>    int i;
>    bool nested_in_vect_loop = false;
>    tree init_value;
> -  REAL_VALUE_TYPE real_init_val = dconst0;
> +  REAL_VALUE_TYPE real_init_val = dconst<0> ();
>    int int_init_val = 0;
>    gimple *def_stmt = NULL;
>
> @@ -3886,7 +3886,7 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
>
>          if (code == MULT_EXPR)
>            {
> -            real_init_val = dconst1;
> +            real_init_val = dconst<1> ();
>              int_init_val = 1;
>            }
>
> diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
> index 48b5298..e78de75 100644
> --- a/gcc/tree-vect-patterns.c
> +++ b/gcc/tree-vect-patterns.c
> @@ -1084,7 +1084,7 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
>    if ((tree_fits_shwi_p (exp)
>         && tree_to_shwi (exp) == 2)
>        || (TREE_CODE (exp) == REAL_CST
> -          && real_equal (&TREE_REAL_CST (exp), &dconst2)))
> +         && real_equal (&TREE_REAL_CST (exp), &dconst<2> ())))
>      {
>        *type_in = TREE_TYPE (base);
>
> @@ -1095,7 +1095,7 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
>
>    /* Catch square root.  */
>    if (TREE_CODE (exp) == REAL_CST
> -      && real_equal (&TREE_REAL_CST (exp), &dconsthalf))
> +      && real_equal (&TREE_REAL_CST (exp), &dconst<1, 2> ()))
>      {
>        tree newfn = mathfn_built_in (TREE_TYPE (base), BUILT_IN_SQRT);
>        *type_in = get_vectype_for_scalar_type (TREE_TYPE (base));
> diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
> index 7a2d623..3b8e26b 100644
> --- a/gcc/tree-vect-slp.c
> +++ b/gcc/tree-vect-slp.c
> @@ -2617,7 +2617,7 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
>            case BIT_IOR_EXPR:
>            case BIT_XOR_EXPR:
>               if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (op)))
> -               neutral_op = build_real (TREE_TYPE (op), dconst0);
> +               neutral_op = build_real (TREE_TYPE (op), dconst<0> ());
>               else
>                 neutral_op = build_int_cst (TREE_TYPE (op), 0);
>
> @@ -2625,7 +2625,7 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
>
>            case MULT_EXPR:
>               if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (op)))
> -               neutral_op = build_real (TREE_TYPE (op), dconst1);
> +               neutral_op = build_real (TREE_TYPE (op), dconst<1> ());
>               else
>                 neutral_op = build_int_cst (TREE_TYPE (op), 1);
>
> diff --git a/gcc/tree.c b/gcc/tree.c
> index f78a2c2..ef70b03 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -1991,7 +1991,7 @@ build_one_cst (tree type)
>        return build_int_cst (type, 1);
>
>      case REAL_TYPE:
> -      return build_real (type, dconst1);
> +      return build_real (type, dconst<1> ());
>
>      case FIXED_POINT_TYPE:
>        /* We can only generate 1 for accum types.  */
> @@ -2044,7 +2044,7 @@ build_minus_one_cst (tree type)
>        return build_int_cst (type, -1);
>
>      case REAL_TYPE:
> -      return build_real (type, dconstm1);
> +      return build_real (type, dconst<-1> ());
>
>      case FIXED_POINT_TYPE:
>        /* We can only generate 1 for accum types.  */
> @@ -2084,7 +2084,7 @@ build_zero_cst (tree type)
>        return build_int_cst (type, 0);
>
>      case REAL_TYPE:
> -      return build_real (type, dconst0);
> +      return build_real (type, dconst<0> ());
>
>      case FIXED_POINT_TYPE:
>        return build_fixed (type, FCONST0 (TYPE_MODE (type)));
> @@ -2554,7 +2554,7 @@ real_zerop (const_tree expr)
>    switch (TREE_CODE (expr))
>      {
>      case REAL_CST:
> -      return real_equal (&TREE_REAL_CST (expr), &dconst0)
> +      return real_equal (&TREE_REAL_CST (expr), &dconst<0> ())
>              && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
>      case COMPLEX_CST:
>        return real_zerop (TREE_REALPART (expr))
> @@ -2584,7 +2584,7 @@ real_onep (const_tree expr)
>    switch (TREE_CODE (expr))
>      {
>      case REAL_CST:
> -      return real_equal (&TREE_REAL_CST (expr), &dconst1)
> +      return real_equal (&TREE_REAL_CST (expr), &dconst<1> ())
>              && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
>      case COMPLEX_CST:
>        return real_onep (TREE_REALPART (expr))
> @@ -2613,7 +2613,7 @@ real_minus_onep (const_tree expr)
>    switch (TREE_CODE (expr))
>      {
>      case REAL_CST:
> -      return real_equal (&TREE_REAL_CST (expr), &dconstm1)
> +      return real_equal (&TREE_REAL_CST (expr), &dconst<-1> ())
>              && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
>      case COMPLEX_CST:
>        return real_minus_onep (TREE_REALPART (expr))
> diff --git a/gcc/ubsan.c b/gcc/ubsan.c
> index af586e3..fe2491c 100644
> --- a/gcc/ubsan.c
> +++ b/gcc/ubsan.c
> @@ -1496,7 +1496,7 @@ ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
>          in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
>          EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
>          either representable or infinity.  */
> -      REAL_VALUE_TYPE maxval = dconst1;
> +      REAL_VALUE_TYPE maxval = dconst<1> ();
>        SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
>        real_convert (&maxval, mode, &maxval);
>        max = build_real (expr_type, maxval);
> @@ -1508,10 +1508,10 @@ ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
>         {
>           /* TYPE_MIN_VALUE is generally representable (or -inf),
>              but TYPE_MIN_VALUE - 1.0 might not be.  */
> -         REAL_VALUE_TYPE minval = dconstm1, minval2;
> +         REAL_VALUE_TYPE minval = dconst<-1> (), minval2;
>           SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
>           real_convert (&minval, mode, &minval);
> -         real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
> +         real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst<1> ());
>           real_convert (&minval2, mode, &minval2);
>           if (real_compare (EQ_EXPR, &minval, &minval2)
>               && !real_isinf (&minval))
> @@ -1522,7 +1522,7 @@ ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
>                  of base digits, we want to subtract a number that
>                  will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
>                  times smaller than minval.  */
> -             minval2 = dconst1;
> +             minval2 = dconst<1> ();
>               gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
>               SET_REAL_EXP (&minval2,
>                             REAL_EXP (&minval2) + prec - 1
>
Richard Sandiford Oct. 7, 2015, 8:15 a.m. UTC | #11
Bernd Schmidt <bschmidt@redhat.com> writes:
> On 10/05/2015 07:00 PM, Richard Sandiford wrote:
>>
>> If my original patch isn't acceptable,
>
> I thought I'd approved it.

In the end I applied the original version.  We can look at a more C++
way of doing things once real_value itself becomes more C++-like.

Thanks,
Richard
diff mbox

Patch

diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index f1e2dcb..f00dfee 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -9048,7 +9048,7 @@  convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
       /* Compute the exact value calc_type'Pred (0.5) at compile time.  */
       fmt = REAL_MODE_FORMAT (TYPE_MODE (calc_type));
       real_2expN (&half_minus_pred_half, -(fmt->p) - 1, TYPE_MODE (calc_type));
-      real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf,
+      real_arithmetic (&pred_half, MINUS_EXPR, &dconst<1, 2> (),
 		       &half_minus_pred_half);
       gnu_pred_half = build_real (calc_type, pred_half);
 
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 89bea60..85ba6dd 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -2659,7 +2659,7 @@  expand_builtin_cexpi (tree exp, rtx target)
 	}
 
       narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
-			  build_real (type, dconst0), arg);
+			  build_real (type, dconst<0> ()), arg);
 
       /* Make sure not to fold the cexp call again.  */
       call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
@@ -4983,7 +4983,7 @@  expand_builtin_signbit (tree exp, rtx target)
     gcc_assert (!fmt->has_signed_zero || !HONOR_SIGNED_ZEROS (fmode));
 
     arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
-		       build_real (TREE_TYPE (arg), dconst0));
+		       build_real (TREE_TYPE (arg), dconst<0> ()));
     return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
   }
 
@@ -7642,7 +7642,7 @@  fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
 static tree
 build_complex_cproj (tree type, bool neg)
 {
-  REAL_VALUE_TYPE rinf, rzero = dconst0;
+  REAL_VALUE_TYPE rinf, rzero = dconst<0> ();
   
   real_inf (&rinf);
   rzero.sign = neg;
@@ -7720,7 +7720,7 @@  fold_builtin_sqrt (location_t loc, tree arg, tree type)
     return NULL_TREE;
 
   /* Calculate the result when the argument is a constant.  */
-  if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
+  if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst<0> (), NULL, true)))
     return res;
 
   /* Optimize sqrt(expN(x)) = expN(x*0.5).  */
@@ -7730,7 +7730,7 @@  fold_builtin_sqrt (location_t loc, tree arg, tree type)
       tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
       arg = fold_build2_loc (loc, MULT_EXPR, type,
 			 CALL_EXPR_ARG (arg, 0),
-			 build_real (type, dconsthalf));
+			 build_real (type, dconst<1, 2> ()));
       return build_call_expr_loc (loc, expfn, 1, arg);
     }
 
@@ -7742,20 +7742,10 @@  fold_builtin_sqrt (location_t loc, tree arg, tree type)
       if (powfn)
 	{
 	  tree arg0 = CALL_EXPR_ARG (arg, 0);
-	  tree tree_root;
-	  /* The inner root was either sqrt or cbrt.  */
-	  /* This was a conditional expression but it triggered a bug
-	     in Sun C 5.5.  */
-	  REAL_VALUE_TYPE dconstroot;
-	  if (BUILTIN_SQRT_P (fcode))
-	    dconstroot = dconsthalf;
-	  else
-	    dconstroot = dconst_third ();
-
-	  /* Adjust for the outer root.  */
-	  SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
-	  tree_root = build_real_truncate (type, dconstroot);
-	  return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
+	  tree arg1 = (BUILTIN_SQRT_P (fcode)
+		       ? build_real (type, dconst<1, 4> ())
+		       : build_real_truncate (type, dconst<1, 6> ()));
+	  return build_call_expr_loc (loc, powfn, 2, arg0, arg1);
 	}
     }
 
@@ -7772,7 +7762,7 @@  fold_builtin_sqrt (location_t loc, tree arg, tree type)
       if (!tree_expr_nonnegative_p (arg0))
 	arg0 = build1 (ABS_EXPR, type, arg0);
       narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
-			   build_real (type, dconsthalf));
+			   build_real (type, dconst<1, 2> ()));
       return build_call_expr_loc (loc, powfn, 2, arg0, narg1);
     }
 
@@ -7803,7 +7793,7 @@  fold_builtin_cbrt (location_t loc, tree arg, tree type)
 	  tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
 	  arg = fold_build2_loc (loc, MULT_EXPR, type,
 				 CALL_EXPR_ARG (arg, 0),
-				 build_real_truncate (type, dconst_third ()));
+				 build_real_truncate (type, dconst<1, 3> ()));
 	  return build_call_expr_loc (loc, expfn, 1, arg);
 	}
 
@@ -7815,11 +7805,7 @@  fold_builtin_cbrt (location_t loc, tree arg, tree type)
 	  if (powfn)
 	    {
 	      tree arg0 = CALL_EXPR_ARG (arg, 0);
-	      tree tree_root;
-	      REAL_VALUE_TYPE dconstroot = dconst_third ();
-
-	      SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
-	      tree_root = build_real_truncate (type, dconstroot);
+	      tree tree_root = build_real_truncate (type, dconst<1, 6> ());
 	      return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
 	    }
 	}
@@ -7834,12 +7820,7 @@  fold_builtin_cbrt (location_t loc, tree arg, tree type)
 
 	      if (powfn)
 		{
-		  tree tree_root;
-		  REAL_VALUE_TYPE dconstroot;
-
-		  real_arithmetic (&dconstroot, MULT_EXPR,
-                                   dconst_third_ptr (), dconst_third_ptr ());
-		  tree_root = build_real_truncate (type, dconstroot);
+		  tree tree_root = build_real_truncate (type, dconst<1, 9> ());
 		  return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
 		}
 	    }
@@ -7855,7 +7836,7 @@  fold_builtin_cbrt (location_t loc, tree arg, tree type)
 	  if (tree_expr_nonnegative_p (arg00))
 	    {
 	      tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
-	      tree c = build_real_truncate (type, dconst_third ());
+	      tree c = build_real_truncate (type, dconst<1, 3> ());
 	      tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01, c);
 	      return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
 	    }
@@ -8407,7 +8388,8 @@  fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
 
   /* Optimize pow(1.0,y) = 1.0.  */
   if (real_onep (arg0))
-    return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
+    return omit_one_operand_loc (loc, type,
+				 build_real (type, dconst<1> ()), arg1);
 
   if (TREE_CODE (arg1) == REAL_CST
       && !TREE_OVERFLOW (arg1))
@@ -8419,22 +8401,22 @@  fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
       c = TREE_REAL_CST (arg1);
 
       /* Optimize pow(x,0.0) = 1.0.  */
-      if (real_equal (&c, &dconst0))
-	return omit_one_operand_loc (loc, type, build_real (type, dconst1),
-				 arg0);
+      if (real_equal (&c, &dconst<0> ()))
+	return omit_one_operand_loc (loc, type,
+				     build_real (type, dconst<1> ()), arg0);
 
       /* Optimize pow(x,1.0) = x.  */
-      if (real_equal (&c, &dconst1))
+      if (real_equal (&c, &dconst<1> ()))
 	return arg0;
 
       /* Optimize pow(x,-1.0) = 1.0/x.  */
-      if (real_equal (&c, &dconstm1))
+      if (real_equal (&c, &dconst<-1> ()))
 	return fold_build2_loc (loc, RDIV_EXPR, type,
-			    build_real (type, dconst1), arg0);
+			    build_real (type, dconst<1> ()), arg0);
 
       /* Optimize pow(x,0.5) = sqrt(x).  */
       if (flag_unsafe_math_optimizations
-	  && real_equal (&c, &dconsthalf))
+	  && real_equal (&c, &dconst<1, 2> ()))
 	{
 	  tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
 
@@ -8446,7 +8428,7 @@  fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
       if (flag_unsafe_math_optimizations)
 	{
 	  const REAL_VALUE_TYPE dconstroot
-	    = real_value_truncate (TYPE_MODE (type), dconst_third ());
+	    = real_value_truncate (TYPE_MODE (type), dconst<1, 3> ());
 
 	  if (real_equal (&c, &dconstroot))
 	    {
@@ -8467,7 +8449,7 @@  fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
 	      && !TREE_OVERFLOW (arg0)
 	      && (n > 0
 		  || (!flag_trapping_math && !flag_errno_math)
-		  || !real_equal (&TREE_REAL_CST (arg0), &dconst0)))
+		  || !real_equal (&TREE_REAL_CST (arg0), &dconst<0> ())))
 	    {
 	      REAL_VALUE_TYPE x;
 	      bool inexact;
@@ -8506,7 +8488,7 @@  fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
 	{
 	  tree narg0 = CALL_EXPR_ARG (arg0, 0);
 	  tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
-				    build_real (type, dconsthalf));
+				    build_real (type, dconst<1, 2> ()));
 	  return build_call_expr_loc (loc, fndecl, 2, narg0, narg1);
 	}
 
@@ -8516,7 +8498,7 @@  fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
 	  tree arg = CALL_EXPR_ARG (arg0, 0);
 	  if (tree_expr_nonnegative_p (arg))
 	    {
-	      tree c = build_real_truncate (type, dconst_third ());
+	      tree c = build_real_truncate (type, dconst<1, 3> ());
 	      tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1, c);
 	      return build_call_expr_loc (loc, fndecl, 2, arg, narg1);
 	    }
@@ -8552,7 +8534,8 @@  fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
 
   /* Optimize pow(1.0,y) = 1.0.  */
   if (real_onep (arg0))
-    return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
+    return omit_one_operand_loc (loc, type,
+				 build_real (type, dconst<1> ()), arg1);
 
   if (tree_fits_shwi_p (arg1))
     {
@@ -8570,8 +8553,8 @@  fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
 
       /* Optimize pow(x,0) = 1.0.  */
       if (c == 0)
-	return omit_one_operand_loc (loc, type, build_real (type, dconst1),
-				 arg0);
+	return omit_one_operand_loc (loc, type,
+				     build_real (type, dconst<1> ()), arg0);
 
       /* Optimize pow(x,1) = x.  */
       if (c == 1)
@@ -8580,7 +8563,7 @@  fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
       /* Optimize pow(x,-1) = 1.0/x.  */
       if (c == -1)
 	return fold_build2_loc (loc, RDIV_EXPR, type,
-			   build_real (type, dconst1), arg0);
+				build_real (type, dconst<1> ()), arg0);
     }
 
   return NULL_TREE;
@@ -8922,7 +8905,8 @@  fold_builtin_signbit (location_t loc, tree arg, tree type)
   if (!HONOR_SIGNED_ZEROS (arg))
     return fold_convert (type,
 			 fold_build2_loc (loc, LT_EXPR, boolean_type_node, arg,
-			build_real (TREE_TYPE (arg), dconst0)));
+					  build_real (TREE_TYPE (arg),
+						      dconst<0> ())));
 
   return NULL_TREE;
 }
@@ -9398,7 +9382,7 @@  fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
 	break;
       case rvc_inf:
 	/* For +-Inf, return (*arg1 = arg0, +-0).  */
-	frac = dconst0;
+	frac = dconst<0> ();
 	frac.sign = value->sign;
 	trunc = *value;
 	break;
@@ -9536,7 +9520,7 @@  fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
 	{
 	  r = TREE_REAL_CST (arg);
 	  if (real_isinf (&r))
-	    return real_compare (GT_EXPR, &r, &dconst0)
+	    return real_compare (GT_EXPR, &r, &dconst<0> ())
 		   ? integer_one_node : integer_minus_one_node;
 	  else
 	    return integer_zero_node;
@@ -9651,7 +9635,7 @@  fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
 	     (x == 0 ? FP_ZERO : FP_SUBNORMAL))).  */
 
   tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
-		     build_real (type, dconst0));
+		     build_real (type, dconst<0> ()));
   res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
 		     tmp, fp_zero, fp_subnormal);
 
@@ -9967,13 +9951,13 @@  fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
     CASE_FLT_FN (BUILT_IN_ASIN):
       if (validate_arg (arg0, REAL_TYPE))
 	return do_mpfr_arg1 (arg0, type, mpfr_asin,
-			     &dconstm1, &dconst1, true);
+			     &dconst<-1> (), &dconst<1> (), true);
     break;
 
     CASE_FLT_FN (BUILT_IN_ACOS):
       if (validate_arg (arg0, REAL_TYPE))
 	return do_mpfr_arg1 (arg0, type, mpfr_acos,
-			     &dconstm1, &dconst1, true);
+			     &dconst<-1> (), &dconst<1> (), true);
     break;
 
     CASE_FLT_FN (BUILT_IN_ATAN):
@@ -9989,13 +9973,13 @@  fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
     CASE_FLT_FN (BUILT_IN_ACOSH):
       if (validate_arg (arg0, REAL_TYPE))
 	return do_mpfr_arg1 (arg0, type, mpfr_acosh,
-			     &dconst1, NULL, true);
+			     &dconst<1> (), NULL, true);
     break;
 
     CASE_FLT_FN (BUILT_IN_ATANH):
       if (validate_arg (arg0, REAL_TYPE))
 	return do_mpfr_arg1 (arg0, type, mpfr_atanh,
-			     &dconstm1, &dconst1, false);
+			     &dconst<-1> (), &dconst<1> (), false);
     break;
 
     CASE_FLT_FN (BUILT_IN_SIN):
@@ -10062,23 +10046,25 @@  fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
 
     CASE_FLT_FN (BUILT_IN_LOG):
       if (validate_arg (arg0, REAL_TYPE))
-        return do_mpfr_arg1 (arg0, type, mpfr_log, &dconst0, NULL, false);
+	return do_mpfr_arg1 (arg0, type, mpfr_log, &dconst<0> (), NULL, false);
       break;
 
     CASE_FLT_FN (BUILT_IN_LOG2):
       if (validate_arg (arg0, REAL_TYPE))
-        return do_mpfr_arg1 (arg0, type, mpfr_log2, &dconst0, NULL, false);
+	return do_mpfr_arg1 (arg0, type, mpfr_log2,
+			     &dconst<0> (), NULL, false);
       break;
 
     CASE_FLT_FN (BUILT_IN_LOG10):
       if (validate_arg (arg0, REAL_TYPE))
-        return do_mpfr_arg1 (arg0, type, mpfr_log10, &dconst0, NULL, false);
+	return do_mpfr_arg1 (arg0, type, mpfr_log10,
+			     &dconst<0> (), NULL, false);
       break;
 
     CASE_FLT_FN (BUILT_IN_LOG1P):
       if (validate_arg (arg0, REAL_TYPE))
 	return do_mpfr_arg1 (arg0, type, mpfr_log1p,
-			     &dconstm1, NULL, false);
+			     &dconst<-1> (), NULL, false);
     break;
 
     CASE_FLT_FN (BUILT_IN_J0):
@@ -10096,13 +10082,13 @@  fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
     CASE_FLT_FN (BUILT_IN_Y0):
       if (validate_arg (arg0, REAL_TYPE))
 	return do_mpfr_arg1 (arg0, type, mpfr_y0,
-			     &dconst0, NULL, false);
+			     &dconst<0> (), NULL, false);
     break;
 
     CASE_FLT_FN (BUILT_IN_Y1):
       if (validate_arg (arg0, REAL_TYPE))
 	return do_mpfr_arg1 (arg0, type, mpfr_y1,
-			     &dconst0, NULL, false);
+			     &dconst<0> (), NULL, false);
     break;
 
     CASE_FLT_FN (BUILT_IN_NAN):
@@ -10247,7 +10233,7 @@  fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1)
       if (validate_arg (arg0, INTEGER_TYPE)
 	  && validate_arg (arg1, REAL_TYPE))
 	return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
-				 &dconst0, false);
+				 &dconst<0> (), false);
     break;
 
     CASE_FLT_FN (BUILT_IN_DREM):
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 4b64a44..9d1126b 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -4983,7 +4983,7 @@  c_common_truthvalue_conversion (location_t location, tree expr)
 				  : truthvalue_true_node;
 
     case REAL_CST:
-      return real_compare (NE_EXPR, &TREE_REAL_CST (expr), &dconst0)
+      return real_compare (NE_EXPR, &TREE_REAL_CST (expr), &dconst<0> ())
 	     ? truthvalue_true_node
 	     : truthvalue_false_node;
 
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index c69f4a6..30db6a9 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -914,9 +914,9 @@  interpret_float (const cpp_token *token, unsigned int flags,
 	}
     }
   /* We also give a warning if the value underflows.  */
-  else if (real_equal (&real, &dconst0)
+  else if (real_equal (&real, &dconst<0> ())
 	   || (const_type != type
-	       && real_equal (&real_trunc, &dconst0)))
+	       && real_equal (&real_trunc, &dconst<0> ())))
     {
       REAL_VALUE_TYPE realvoidmode;
       int oflow = real_from_string (&realvoidmode, copy);
@@ -924,7 +924,7 @@  interpret_float (const cpp_token *token, unsigned int flags,
 			      : (oflow < 0 ? OT_UNDERFLOW : OT_OVERFLOW));
       if (!(flags & CPP_N_USERDEF))
 	{
-	  if (oflow < 0 || !real_equal (&realvoidmode, &dconst0))
+	  if (oflow < 0 || !real_equal (&realvoidmode, &dconst<0> ()))
 	    warning (OPT_Woverflow, "floating constant truncated to zero");
 	}
     }
diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
index 672762c..68b76b8 100644
--- a/gcc/c-family/c-ubsan.c
+++ b/gcc/c-family/c-ubsan.c
@@ -65,7 +65,7 @@  ubsan_instrument_division (location_t loc, tree op0, tree op1)
   else if (TREE_CODE (type) == REAL_TYPE
 	   && (flag_sanitize & SANITIZE_FLOAT_DIVIDE))
     t = fold_build2 (EQ_EXPR, boolean_type_node,
-		     op1, build_real (type, dconst0));
+		     op1, build_real (type, dconst<0> ()));
   else
     return NULL_TREE;
 
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index c9fe368..7fe1831 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -3768,7 +3768,7 @@  aarch64_float_const_zero_rtx_p (rtx x)
 
   if (REAL_VALUE_MINUS_ZERO (*CONST_DOUBLE_REAL_VALUE (x)))
     return !HONOR_SIGNED_ZEROS (GET_MODE (x));
-  return real_equal (CONST_DOUBLE_REAL_VALUE (x), &dconst0);
+  return real_equal (CONST_DOUBLE_REAL_VALUE (x), &dconst<0> ());
 }
 
 /* Return the fixed registers used for condition codes.  */
diff --git a/gcc/config/c6x/c6x.md b/gcc/config/c6x/c6x.md
index fa89587..7824cd7 100644
--- a/gcc/config/c6x/c6x.md
+++ b/gcc/config/c6x/c6x.md
@@ -2809,7 +2809,8 @@ 
   "TARGET_FP && flag_reciprocal_math"
 {
   operands[3] = force_reg (SFmode,
-			   const_double_from_real_value (dconst2, SFmode));
+			   const_double_from_real_value (dconst<2> (),
+							 SFmode));
   operands[4] = gen_reg_rtx (SFmode);
   operands[5] = gen_reg_rtx (SFmode);
   operands[6] = gen_reg_rtx (SFmode);
@@ -2834,7 +2835,8 @@ 
   "TARGET_FP && flag_reciprocal_math"
 {
   operands[3] = force_reg (DFmode,
-			   const_double_from_real_value (dconst2, DFmode));
+			   const_double_from_real_value (dconst<2> (),
+							 DFmode));
   operands[4] = gen_reg_rtx (DFmode);
   operands[5] = gen_reg_rtx (DFmode);
   operands[6] = gen_reg_rtx (DFmode);
diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c
index 6afd5d4..20ab6e4 100644
--- a/gcc/config/fr30/fr30.c
+++ b/gcc/config/fr30/fr30.c
@@ -889,7 +889,7 @@  fr30_const_double_is_zero (rtx operand)
   if (operand == NULL || GET_CODE (operand) != CONST_DOUBLE)
     return 0;
 
-  return real_equal (CONST_DOUBLE_REAL_VALUE (operand), &dconst0);
+  return real_equal (CONST_DOUBLE_REAL_VALUE (operand), &dconst<0> ());
 }
 
 /*}}}*/
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index d59b59b..5591f78 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -10511,7 +10511,7 @@  standard_80387_constant_p (rtx x)
      fldz;fchs or fld1;fchs sequence.  */
   if (real_isnegzero (r))
     return 8;
-  if (real_identical (r, &dconstm1))
+  if (real_identical (r, &dconst<-1> ()))
     return 9;
 
   return 0;
@@ -20296,8 +20296,8 @@  ix86_expand_convert_uns_didf_sse (rtx target, rtx input)
 
   /* Subtract off those 0x1.0p52 and 0x1.0p84 biases, to produce values
      in [0,2**32-1] and [0]+[2**32,2**64-1] respectively.  */
-  real_ldexp (&bias_lo_rvt, &dconst1, 52);
-  real_ldexp (&bias_hi_rvt, &dconst1, 84);
+  real_ldexp (&bias_lo_rvt, &dconst<1> (), 52);
+  real_ldexp (&bias_hi_rvt, &dconst<1> (), 84);
   biases = const_double_from_real_value (bias_lo_rvt, DFmode);
   x = const_double_from_real_value (bias_hi_rvt, DFmode);
   biases = gen_rtx_CONST_VECTOR (V2DFmode, gen_rtvec (2, biases, x));
@@ -20339,7 +20339,7 @@  ix86_expand_convert_uns_sidf_sse (rtx target, rtx input)
   fp = gen_reg_rtx (DFmode);
   emit_insn (gen_floatsidf2 (fp, x));
 
-  real_ldexp (&TWO31r, &dconst1, 31);
+  real_ldexp (&TWO31r, &dconst<1> (), 31);
   x = const_double_from_real_value (TWO31r, DFmode);
 
   x = expand_simple_binop (DFmode, PLUS, fp, x, target, 0, OPTAB_DIRECT);
@@ -20361,7 +20361,7 @@  ix86_expand_convert_sign_didf_sse (rtx target, rtx input)
 
   emit_insn (gen_floatsidf2 (fp_hi, gen_highpart (SImode, input)));
 
-  real_ldexp (&TWO32r, &dconst1, 32);
+  real_ldexp (&TWO32r, &dconst<1> (), 32);
   x = const_double_from_real_value (TWO32r, DFmode);
   fp_hi = expand_simple_binop (DFmode, MULT, fp_hi, x, fp_hi, 0, OPTAB_DIRECT);
 
@@ -20381,7 +20381,7 @@  ix86_expand_convert_uns_sisf_sse (rtx target, rtx input)
   REAL_VALUE_TYPE ONE16r;
   rtx fp_hi, fp_lo, int_hi, int_lo, x;
 
-  real_ldexp (&ONE16r, &dconst1, 16);
+  real_ldexp (&ONE16r, &dconst<1> (), 16);
   x = const_double_from_real_value (ONE16r, SFmode);
   int_lo = expand_simple_binop (SImode, AND, input, GEN_INT(0xffff),
 				      NULL, 0, OPTAB_DIRECT);
@@ -20425,7 +20425,7 @@  ix86_expand_vector_convert_uns_vsivsf (rtx target, rtx val)
   emit_insn (cvt (tmp[3], tmp[1]));
   tmp[4] = gen_reg_rtx (fltmode);
   emit_insn (cvt (tmp[4], tmp[2]));
-  real_ldexp (&TWO16r, &dconst1, 16);
+  real_ldexp (&TWO16r, &dconst<1> (), 16);
   tmp[5] = const_double_from_real_value (TWO16r, SFmode);
   tmp[5] = force_reg (fltmode, ix86_build_const_vector (fltmode, 1, tmp[5]));
   tmp[6] = expand_simple_binop (fltmode, MULT, tmp[4], tmp[5], NULL_RTX, 1,
@@ -20454,7 +20454,7 @@  ix86_expand_adjust_ufix_to_sfix_si (rtx val, rtx *xorp)
 
   for (i = 0; i < 3; i++)
     tmp[i] = gen_reg_rtx (mode);
-  real_ldexp (&TWO31r, &dconst1, 31);
+  real_ldexp (&TWO31r, &dconst<1> (), 31);
   two31r = const_double_from_real_value (TWO31r, scalarmode);
   two31r = ix86_build_const_vector (mode, 1, two31r);
   two31r = force_reg (mode, two31r);
@@ -47089,7 +47089,7 @@  void ix86_emit_i387_round (rtx op0, rtx op1)
   e2 = gen_reg_rtx (inmode);
   res = gen_reg_rtx (outmode);
 
-  half = const_double_from_real_value (dconsthalf, inmode);
+  half = const_double_from_real_value (dconst<1, 2> (), inmode);
 
   /* round(a) = sgn(a) * floor(fabs(a) + 0.5) */
 
@@ -47223,7 +47223,7 @@  void ix86_emit_swsqrtsf (rtx res, rtx a, machine_mode mode,
   real_from_integer (&r, VOIDmode, -3, SIGNED);
   mthree = const_double_from_real_value (r, SFmode);
 
-  real_arithmetic (&r, NEGATE_EXPR, &dconsthalf, NULL);
+  real_arithmetic (&r, NEGATE_EXPR, &dconst<1, 2> (), NULL);
   mhalf = const_double_from_real_value (r, SFmode);
   unspec = UNSPEC_RSQRT;
 
@@ -47508,7 +47508,7 @@  ix86_gen_TWO52 (machine_mode mode)
   REAL_VALUE_TYPE TWO52r;
   rtx TWO52;
 
-  real_ldexp (&TWO52r, &dconst1, mode == DFmode ? 52 : 23);
+  real_ldexp (&TWO52r, &dconst<1> (), mode == DFmode ? 52 : 23);
   TWO52 = const_double_from_real_value (TWO52r, mode);
   TWO52 = force_reg (mode, TWO52);
 
@@ -47532,7 +47532,8 @@  ix86_expand_lround (rtx op0, rtx op1)
   /* load nextafter (0.5, 0.0) */
   fmt = REAL_MODE_FORMAT (mode);
   real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
-  real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
+  real_arithmetic (&pred_half, MINUS_EXPR, &dconst<1, 2> (),
+		   &half_minus_pred_half);
 
   /* adj = copysign (0.5, op1) */
   adj = force_reg (mode, const_double_from_real_value (pred_half, mode));
@@ -47664,7 +47665,8 @@  ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
   /* generate 1.0 or -1.0 */
   one = force_reg (mode,
 	           const_double_from_real_value (do_floor
-						 ? dconst1 : dconstm1, mode));
+						 ? dconst<1> ()
+						 : dconst<-1> (), mode));
 
   /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
   tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
@@ -47723,7 +47725,7 @@  ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
   expand_float (xa, xi, 0);
 
   /* generate 1.0 */
-  one = force_reg (mode, const_double_from_real_value (dconst1, mode));
+  one = force_reg (mode, const_double_from_real_value (dconst<1> (), mode));
 
   /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
   tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
@@ -47788,7 +47790,8 @@  ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
   dxa = expand_simple_binop (mode, MINUS, xa2, xa, NULL_RTX, 0, OPTAB_DIRECT);
 
   /* generate 0.5, 1.0 and -0.5 */
-  half = force_reg (mode, const_double_from_real_value (dconsthalf, mode));
+  half = force_reg (mode, const_double_from_real_value (dconst<1, 2> (),
+							mode));
   one = expand_simple_binop (mode, PLUS, half, half, NULL_RTX, 0, OPTAB_DIRECT);
   mhalf = expand_simple_binop (mode, MINUS, half, one, NULL_RTX,
 			       0, OPTAB_DIRECT);
@@ -47898,7 +47901,7 @@  ix86_expand_truncdf_32 (rtx operand0, rtx operand1)
   emit_move_insn (res, tmp);
 
   /* generate 1.0 */
-  one = force_reg (mode, const_double_from_real_value (dconst1, mode));
+  one = force_reg (mode, const_double_from_real_value (dconst<1> (), mode));
 
   /* Compensate: res = xa2 - (res > xa ? 1 : 0)  */
   mask = ix86_expand_sse_compare_mask (UNGT, res, xa, false);
@@ -47946,7 +47949,8 @@  ix86_expand_round (rtx operand0, rtx operand1)
   /* load nextafter (0.5, 0.0) */
   fmt = REAL_MODE_FORMAT (mode);
   real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
-  real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
+  real_arithmetic (&pred_half, MINUS_EXPR, &dconst<1, 2> (),
+		   &half_minus_pred_half);
 
   /* xa = xa + 0.5 */
   half = force_reg (mode, const_double_from_real_value (pred_half, mode));
@@ -47997,7 +48001,8 @@  ix86_expand_round_sse4 (rtx op0, rtx op1)
   /* load nextafter (0.5, 0.0) */
   fmt = REAL_MODE_FORMAT (mode);
   real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
-  real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
+  real_arithmetic (&pred_half, MINUS_EXPR, &dconst<1, 2> (),
+		   &half_minus_pred_half);
   half = const_double_from_real_value (pred_half, mode);
 
   /* e1 = copysign (0.5, op1) */
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 5fcebb5..140bc0f 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -4643,7 +4643,7 @@ 
   if (optimize_insn_for_size_p ())
     FAIL;
 
-  real_ldexp (&TWO31r, &dconst1, 31);
+  real_ldexp (&TWO31r, &dconst<1> (), 31);
   two31 = const_double_from_real_value (TWO31r, mode);
   two31 = ix86_build_const_vector (vecmode, true, two31);
   operands[2] = force_reg (vecmode, two31);
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 9b7a338..a016b26 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -5432,7 +5432,7 @@ 
   rtx x;
   int i;
 
-  real_ldexp (&TWO32r, &dconst1, 32);
+  real_ldexp (&TWO32r, &dconst<1> (), 32);
   x = const_double_from_real_value (TWO32r, DFmode);
 
   operands[3] = force_reg (V2DFmode, CONST0_RTX (V2DFmode));
@@ -5463,7 +5463,7 @@ 
   rtx x;
   int i;
 
-  real_ldexp (&TWO32r, &dconst1, 32);
+  real_ldexp (&TWO32r, &dconst<1> (), 32);
   x = const_double_from_real_value (TWO32r, DFmode);
 
   operands[3] = force_reg (V2DFmode, CONST0_RTX (V2DFmode));
@@ -5483,7 +5483,7 @@ 
   rtx x, tmp[6];
   int i;
 
-  real_ldexp (&TWO32r, &dconst1, 32);
+  real_ldexp (&TWO32r, &dconst<1> (), 32);
   x = const_double_from_real_value (TWO32r, DFmode);
 
   tmp[0] = force_reg (V4DFmode, CONST0_RTX (V4DFmode));
@@ -5508,7 +5508,7 @@ 
   REAL_VALUE_TYPE TWO32r;
   rtx k, x, tmp[4];
 
-  real_ldexp (&TWO32r, &dconst1, 32);
+  real_ldexp (&TWO32r, &dconst<1> (), 32);
   x = const_double_from_real_value (TWO32r, DFmode);
 
   tmp[0] = force_reg (V8DFmode, CONST0_RTX (V8DFmode));
@@ -5534,7 +5534,7 @@ 
   rtx x, tmp[5];
   int i;
 
-  real_ldexp (&TWO32r, &dconst1, 32);
+  real_ldexp (&TWO32r, &dconst<1> (), 32);
   x = const_double_from_real_value (TWO32r, DFmode);
 
   tmp[0] = force_reg (V4DFmode, CONST0_RTX (V4DFmode));
@@ -5557,7 +5557,7 @@ 
   REAL_VALUE_TYPE TWO32r;
   rtx k, x, tmp[3];
 
-  real_ldexp (&TWO32r, &dconst1, 32);
+  real_ldexp (&TWO32r, &dconst<1> (), 32);
   x = const_double_from_real_value (TWO32r, DFmode);
 
   tmp[0] = force_reg (V8DFmode, CONST0_RTX (V8DFmode));
@@ -14881,7 +14881,8 @@ 
   /* load nextafter (0.5, 0.0) */
   fmt = REAL_MODE_FORMAT (scalar_mode);
   real_2expN (&half_minus_pred_half, -(fmt->p) - 1, scalar_mode);
-  real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
+  real_arithmetic (&pred_half, MINUS_EXPR, &dconst<1, 2> (),
+		   &half_minus_pred_half);
   half = const_double_from_real_value (pred_half, scalar_mode);
 
   vec_half = ix86_build_const_vector (<MODE>mode, true, half);
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index bfc19f3..e7226ac 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -4365,7 +4365,7 @@  floating_exact_log2 (rtx x)
 
   r = CONST_DOUBLE_REAL_VALUE (x);
 
-  if (real_less (r, &dconst1))
+  if (real_less (r, &dconst<1> ()))
     return 0;
 
   exp = real_exponent (r);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index c00d730..39a9a75 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -31944,7 +31944,7 @@  rs6000_emit_swdiv (rtx dst, rtx n, rtx d, bool note_p)
 
   gcc_assert (code != CODE_FOR_nothing);
 
-  one = rs6000_load_constant_and_splat (mode, dconst1);
+  one = rs6000_load_constant_and_splat (mode, dconst<1> ());
 
   /* x0 = 1./d estimate */
   x0 = gen_reg_rtx (mode);
@@ -32684,7 +32684,7 @@  rs6000_scale_v2df (rtx tgt, rtx src, int scale)
   rtvec v = rtvec_alloc (2);
   rtx elt;
   rtx scale_vec = gen_reg_rtx (V2DFmode);
-  (void)real_powi (&r_pow, DFmode, &dconst2, hwi_scale);
+  (void)real_powi (&r_pow, DFmode, &dconst<2> (), hwi_scale);
   elt = const_double_from_real_value (r_pow, DFmode);
   RTVEC_ELT (v, 0) = elt;
   RTVEC_ELT (v, 1) = elt;
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index cf40f10..ae4f492 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -10578,7 +10578,7 @@ 
   operands[14] = force_const_mem (DFmode,
 				  const_double_from_real_value (rv, DFmode));
   operands[15] = force_const_mem (DFmode,
-				  const_double_from_real_value (dconst0,
+				  const_double_from_real_value (dconst<0> (),
 								DFmode));
   if (TARGET_TOC)
     {
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 92e9f9f..f7543d1 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -10005,8 +10005,7 @@  fp_zero_operand (rtx op)
   if (GET_MODE (op) != SFmode)
     return false;
 
-  r = CONST_DOUBLE_REAL_VALUE (op);
-  return real_equal (r, &dconst0) && ! REAL_VALUE_MINUS_ZERO (*r);
+  return real_equal (r, &dconst<0> ()) && ! REAL_VALUE_MINUS_ZERO (*r);
 }
 
 /* Returns true if OP is a floating point value with value 1.0.  */
@@ -10016,7 +10015,7 @@  fp_one_operand (rtx op)
   if (GET_MODE (op) != SFmode)
     return false;
 
-  return real_equal (CONST_DOUBLE_REAL_VALUE (op), &dconst1);
+  return real_equal (CONST_DOUBLE_REAL_VALUE (op), &dconst<1> ());
 }
 
 /* Return the TLS type for TLS symbols.  */
diff --git a/gcc/config/xtensa/predicates.md b/gcc/config/xtensa/predicates.md
index 00f2370..81e5ebe 100644
--- a/gcc/config/xtensa/predicates.md
+++ b/gcc/config/xtensa/predicates.md
@@ -150,7 +150,7 @@ 
 (define_predicate "const_float_1_operand"
   (match_code "const_double")
 {
-  return real_equal (CONST_DOUBLE_REAL_VALUE (op), &dconst1);
+  return real_equal (CONST_DOUBLE_REAL_VALUE (op), &dconst<1> ());
 })
 
 (define_predicate "fpmem_offset_operand"
diff --git a/gcc/cprop.c b/gcc/cprop.c
index 4cb8586..f983350 100644
--- a/gcc/cprop.c
+++ b/gcc/cprop.c
@@ -1352,7 +1352,7 @@  implicit_set_cond_p (const_rtx cond)
       /* ??? The complex and vector checks are not implemented yet.  We just
 	 always return zero for them.  */
       if (CONST_DOUBLE_AS_FLOAT_P (cst)
-	  && real_equal (CONST_DOUBLE_REAL_VALUE (cst), &dconst0))
+	  && real_equal (CONST_DOUBLE_REAL_VALUE (cst), &dconst<0> ()))
 	return 0;
       else
 	return 0;
diff --git a/gcc/dfp.c b/gcc/dfp.c
index ceb43d1..6dbdcad 100644
--- a/gcc/dfp.c
+++ b/gcc/dfp.c
@@ -115,22 +115,22 @@  decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn)
 	  /* dconst{1,2,m1,half} are used in various places in
 	     the middle-end and optimizers, allow them here
 	     as an exception by converting them to decimal.  */
-	  if (memcmp (r, &dconst1, sizeof (*r)) == 0)
+	  if (memcmp (r, &dconst<1> (), sizeof (*r)) == 0)
 	    {
 	      decNumberFromString (dn, "1", &set);
 	      break;
 	    }
-	  if (memcmp (r, &dconst2, sizeof (*r)) == 0)
+	  if (memcmp (r, &dconst<2> (), sizeof (*r)) == 0)
 	    {
 	      decNumberFromString (dn, "2", &set);
 	      break;
 	    }
-	  if (memcmp (r, &dconstm1, sizeof (*r)) == 0)
+	  if (memcmp (r, &dconst<-1> (), sizeof (*r)) == 0)
 	    {
 	      decNumberFromString (dn, "-1", &set);
 	      break;
 	    }
-	  if (memcmp (r, &dconsthalf, sizeof (*r)) == 0)
+	  if (memcmp (r, &dconst<1, 2> (), sizeof (*r)) == 0)
 	    {
 	      decNumberFromString (dn, "0.5", &set);
 	      break;
diff --git a/gcc/doc/match-and-simplify.texi b/gcc/doc/match-and-simplify.texi
index c5c2b7e..cc1f573 100644
--- a/gcc/doc/match-and-simplify.texi
+++ b/gcc/doc/match-and-simplify.texi
@@ -165,7 +165,7 @@  chain conditions avoiding nesting @code{if}s too much:
  (switch
   /* a CMP (-0) -> a CMP 0  */
   (if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@@1)))
-   (cmp @@0 @{ build_real (TREE_TYPE (@@1), dconst0); @}))
+   (cmp @@0 @{ build_real (TREE_TYPE (@@1), dconst<0> ()); @}))
   /* x != NaN is always true, other ops are always false.  */
   (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@@1))
        && ! HONOR_SNANS (@@1))
@@ -180,7 +180,7 @@  Is equal to
  (switch
   /* a CMP (-0) -> a CMP 0  */
   (if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@@1)))
-   (cmp @@0 @{ build_real (TREE_TYPE (@@1), dconst0); @})
+   (cmp @@0 @{ build_real (TREE_TYPE (@@1), dconst<0> ()); @})
    /* x != NaN is always true, other ops are always false.  */
    (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@@1))
         && ! HONOR_SNANS (@@1))
@@ -310,7 +310,8 @@  be added to a new @code{for}.  For example
 (define_operator_list POW BUILT_IN_POWF BUILT_IN_POW BUILT_IN_POWL)
 (simplify
  (SQRT (POW @@0 @@1))
- (POW (abs @@0) (mult @@1 @{ built_real (TREE_TYPE (@@1), dconsthalf); @})))
+ (POW (abs @@0) (mult @@1 @{ build_real (TREE_TYPE (@@1),
+                                      dconst<1, 2> ()); @})))
 @end smallexample
 
 is the same as
@@ -320,7 +321,8 @@  is the same as
      POW (BUILT_IN_POWF BUILT_IN_POW BUILT_IN_POWL)
  (simplify
   (SQRT (POW @@0 @@1))
-  (POW (abs @@0) (mult @@1 @{ built_real (TREE_TYPE (@@1), dconsthalf); @}))))
+  (POW (abs @@0) (mult @@1 @{ build_real (TREE_TYPE (@@1),
+                                       dconst<1, 2> ()); @}))))
 @end smallexample
 
 Another building block are @code{with} expressions in the
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index c418c24..7d1dc5e 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -104,12 +104,6 @@  rtx const_tiny_rtx[4][(int) MAX_MACHINE_MODE];
 
 rtx const_true_rtx;
 
-REAL_VALUE_TYPE dconst0;
-REAL_VALUE_TYPE dconst1;
-REAL_VALUE_TYPE dconst2;
-REAL_VALUE_TYPE dconstm1;
-REAL_VALUE_TYPE dconsthalf;
-
 /* Record fixed-point constant 0 and 1.  */
 FIXED_VALUE_TYPE fconst0[MAX_FCONST0];
 FIXED_VALUE_TYPE fconst1[MAX_FCONST1];
@@ -5878,7 +5872,6 @@  init_emit_once (void)
 {
   int i;
   machine_mode mode;
-  machine_mode double_mode;
 
   /* Initialize the CONST_INT, CONST_WIDE_INT, CONST_DOUBLE,
      CONST_FIXED, and memory attribute hash tables.  */
@@ -5917,20 +5910,10 @@  init_emit_once (void)
 
   double_mode = mode_for_size (DOUBLE_TYPE_SIZE, MODE_FLOAT, 0);
 
-  real_from_integer (&dconst0, double_mode, 0, SIGNED);
-  real_from_integer (&dconst1, double_mode, 1, SIGNED);
-  real_from_integer (&dconst2, double_mode, 2, SIGNED);
-
-  dconstm1 = dconst1;
-  dconstm1.sign = 1;
-
-  dconsthalf = dconst1;
-  SET_REAL_EXP (&dconsthalf, REAL_EXP (&dconsthalf) - 1);
-
   for (i = 0; i < 3; i++)
     {
       const REAL_VALUE_TYPE *const r =
-	(i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2);
+	(i == 0 ? &dconst<0> () : i == 1 ? &dconst<1> () : &dconst<2> ());
 
       for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
 	   mode != VOIDmode;
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 93cf508..6327993 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -3235,7 +3235,7 @@  expand_mult (machine_mode mode, rtx op0, rtx op1, rtx target,
 
   /* Expand x*2.0 as x+x.  */
   if (CONST_DOUBLE_AS_FLOAT_P (scalar_op1)
-      && real_equal (CONST_DOUBLE_REAL_VALUE (scalar_op1), &dconst2))
+      && real_equal (CONST_DOUBLE_REAL_VALUE (scalar_op1), &dconst<2> ()))
     {
       op0 = force_reg (GET_MODE (op0), op0);
       return expand_binop (mode, add_optab, op0, op0,
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 2851a29..60149c8 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1176,7 +1176,7 @@  const_binop (enum tree_code code, tree arg1, tree arg2)
       /* Don't perform operation if it would raise a division
 	 by zero exception.  */
       if (code == RDIV_EXPR
-	  && real_equal (&d2, &dconst0)
+	  && real_equal (&d2, &dconst<0> ())
 	  && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode)))
 	return NULL_TREE;
 
@@ -3600,9 +3600,9 @@  distribute_real_division (location_t loc, enum tree_code code, tree type,
       r0 = TREE_REAL_CST (TREE_OPERAND (arg0, 1));
       r1 = TREE_REAL_CST (TREE_OPERAND (arg1, 1));
       if (!mul0)
-	real_arithmetic (&r0, RDIV_EXPR, &dconst1, &r0);
+	real_arithmetic (&r0, RDIV_EXPR, &dconst<1> (), &r0);
       if (!mul1)
-        real_arithmetic (&r1, RDIV_EXPR, &dconst1, &r1);
+	real_arithmetic (&r1, RDIV_EXPR, &dconst<1> (), &r1);
       real_arithmetic (&r0, code, &r0, &r1);
       return fold_build2_loc (loc, MULT_EXPR, type,
 			  TREE_OPERAND (arg0, 0),
@@ -9914,7 +9914,7 @@  fold_binary_loc (location_t loc,
 
 		  if (powfn)
 		    {
-		      tree arg = build_real (type, dconst2);
+		      tree arg = build_real (type, dconst<2> ());
 		      return build_call_expr_loc (loc, powfn, 2, arg0, arg);
 		    }
 		}
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index c035fe0..6bb3aa1 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -669,8 +669,8 @@  java_init_decl_processing (void)
                         double_type_node));
   layout_type (double_type_node);
 
-  float_zero_node = build_real (float_type_node, dconst0);
-  double_zero_node = build_real (double_type_node, dconst0);
+  float_zero_node = build_real (float_type_node, dconst<0> ());
+  double_zero_node = build_real (double_type_node, dconst<0> ());
 
   /* These are the vtables for arrays of primitives.  */
   boolean_array_vtable = create_primitive_vtable ("boolean");
diff --git a/gcc/match.pd b/gcc/match.pd
index 9962b0a..8e2069b 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1298,7 +1298,7 @@  along with GCC; see the file COPYING3.  If not see
 (simplify
  (plus @0 @0)
  (if (SCALAR_FLOAT_TYPE_P (type))
-  (mult @0 { build_real (type, dconst2); })))
+  (mult @0 { build_real (type, dconst<2> ()); })))
 
 (simplify
  (minus integer_zerop @1)
@@ -1598,7 +1598,7 @@  along with GCC; see the file COPYING3.  If not see
   (switch
    /* a CMP (-0) -> a CMP 0  */
    (if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@1)))
-    (cmp @0 { build_real (TREE_TYPE (@1), dconst0); }))
+    (cmp @0 { build_real (TREE_TYPE (@1), dconst<0> ()); }))
    /* x != NaN is always true, other ops are always false.  */
    (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@1))
 	&& ! HONOR_SNANS (@1))
@@ -1694,7 +1694,7 @@  along with GCC; see the file COPYING3.  If not see
        (if (cmp == NE_EXPR || !HONOR_NANS (@0))
 	{ constant_boolean_node (true, type); })
        /* sqrt(x) > y is the same as x >= 0, if y is negative.  */
-       (ge @0 { build_real (TREE_TYPE (@0), dconst0); })))
+       (ge @0 { build_real (TREE_TYPE (@0), dconst<0> ()); })))
      (if (cmp == GT_EXPR || cmp == GE_EXPR)
       (with
        {
@@ -1731,11 +1731,11 @@  along with GCC; see the file COPYING3.  If not see
 	 /* sqrt(x) < y is x >= 0 when y is very large and we
 	    don't care about Infinities.  */
 	 (if (! HONOR_INFINITIES (@0))
-	  (ge @0 { build_real (TREE_TYPE (@0), dconst0); }))
+	  (ge @0 { build_real (TREE_TYPE (@0), dconst<0> ()); }))
 	 /* sqrt(x) < y is x >= 0 && x != +Inf, when y is large.  */
 	 (if (GENERIC)
 	  (truth_andif
-	   (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
+	   (ge @0 { build_real (TREE_TYPE (@0), dconst<0> ()); })
 	   (ne @0 { build_real (TREE_TYPE (@0), c2); }))))
 	/* sqrt(x) < c is the same as x < c*c, if we ignore NaNs.  */
 	(if (! HONOR_NANS (@0))
@@ -1743,7 +1743,7 @@  along with GCC; see the file COPYING3.  If not see
 	 /* sqrt(x) < c is the same as x >= 0 && x < c*c.  */
 	 (if (GENERIC)
 	  (truth_andif
-	   (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
+	   (ge @0 { build_real (TREE_TYPE (@0), dconst<0> ()); })
 	   (cmp @0 { build_real (TREE_TYPE (@0), c2); }))))))))))))
 
 /* Unordered tests if either argument is a NaN.  */
@@ -2193,7 +2193,7 @@  along with GCC; see the file COPYING3.  If not see
          break;
        CASE_FLT_FN (BUILT_IN_EXP2):
          /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
-         x = build_real (type, dconst2);
+         x = build_real (type, dconst<2> ());
          break;
        CASE_FLT_FN (BUILT_IN_EXP10):
        CASE_FLT_FN (BUILT_IN_POW10):
@@ -2221,11 +2221,11 @@  along with GCC; see the file COPYING3.  If not see
        {
        CASE_FLT_FN (BUILT_IN_SQRT):
 	 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
-	 x = build_real (type, dconsthalf);
+	 x = build_real (type, dconst<1, 2> ());
          break;
        CASE_FLT_FN (BUILT_IN_CBRT):
 	 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
-         x = build_real_truncate (type, dconst_third ());
+	 x = build_real_truncate (type, dconst<1, 3> ());
          break;
        default:
 	 gcc_unreachable ();
diff --git a/gcc/real.c b/gcc/real.c
index 49d6739..fb77502 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -111,7 +111,6 @@  static void decimal_integer_string (char *, const REAL_VALUE_TYPE *,
 
 static const REAL_VALUE_TYPE * ten_to_ptwo (int);
 static const REAL_VALUE_TYPE * ten_to_mptwo (int);
-static const REAL_VALUE_TYPE * real_digit (int);
 static void times_pten (REAL_VALUE_TYPE *, int);
 
 static void round_for_format (const struct real_format *, REAL_VALUE_TYPE *);
@@ -1273,7 +1272,7 @@  real_identical (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b)
 bool
 exact_real_inverse (machine_mode mode, REAL_VALUE_TYPE *r)
 {
-  const REAL_VALUE_TYPE *one = real_digit (1);
+  const REAL_VALUE_TYPE *one = &dconst<1> ();
   REAL_VALUE_TYPE u;
   int i;
 
@@ -1579,7 +1578,7 @@  real_to_decimal_for_mode (char *str, const REAL_VALUE_TYPE *r_orig,
   if (digits > max_digits)
     digits = max_digits;
 
-  one = real_digit (1);
+  one = &dconst<1> ();
   ten = ten_to_ptwo (0);
 
   sign = r.sign;
@@ -2225,6 +2224,22 @@  real_from_integer (REAL_VALUE_TYPE *r, machine_mode mode,
     real_convert (r, mode, r);
 }
 
+/* Set VALUE to A/B, in maximum precision.  */
+
+void
+real_from_fraction (REAL_VALUE_TYPE *value, int a, int b)
+{
+  if (b == 1)
+    real_from_integer (value, VOIDmode, a, SIGNED);
+  else
+    {
+      REAL_VALUE_TYPE areal, breal;
+      real_from_integer (&areal, VOIDmode, a, SIGNED);
+      real_from_integer (&breal, VOIDmode, b, SIGNED);
+      real_arithmetic (value, RDIV_EXPR, &areal, &breal);
+    }
+}
+
 /* Render R, an integral value, as a floating point constant with no
    specified exponent.  */
 
@@ -2252,7 +2267,7 @@  decimal_integer_string (char *str, const REAL_VALUE_TYPE *r_orig,
   digits = dec_exp + 1;
   gcc_assert ((digits + 2) < (int)buf_size);
 
-  pten = *real_digit (1);
+  pten = dconst<1> ();
   times_pten (&pten, dec_exp);
 
   p = str;
@@ -2326,27 +2341,11 @@  ten_to_mptwo (int n)
   gcc_assert (n < EXP_BITS);
 
   if (tens[n].cl == rvc_zero)
-    do_divide (&tens[n], real_digit (1), ten_to_ptwo (n));
+    do_divide (&tens[n], &dconst<1> (), ten_to_ptwo (n));
 
   return &tens[n];
 }
 
-/* Returns N.  */
-
-static const REAL_VALUE_TYPE *
-real_digit (int n)
-{
-  static REAL_VALUE_TYPE num[10];
-
-  gcc_assert (n >= 0);
-  gcc_assert (n <= 9);
-
-  if (n > 0 && num[n].cl == rvc_zero)
-    real_from_integer (&num[n], VOIDmode, n, UNSIGNED);
-
-  return &num[n];
-}
-
 /* Multiply R by 10**EXP.  */
 
 static void
@@ -2359,7 +2358,7 @@  times_pten (REAL_VALUE_TYPE *r, int exp)
   if (negative)
     {
       exp = -exp;
-      pten = *real_digit (1);
+      pten = dconst<1> ();
       rr = &pten;
     }
   else
@@ -2395,22 +2394,6 @@  dconst_e_ptr (void)
   return &value;
 }
 
-/* Returns the special REAL_VALUE_TYPE corresponding to 1/3.  */
-
-const REAL_VALUE_TYPE *
-dconst_third_ptr (void)
-{
-  static REAL_VALUE_TYPE value;
-
-  /* Initialize mathematical constants for constant folding builtins.
-     These constants need to be given to at least 160 bits precision.  */
-  if (value.cl == rvc_zero)
-    {
-      real_arithmetic (&value, RDIV_EXPR, &dconst1, real_digit (3));
-    }
-  return &value;
-}
-
 /* Returns the special REAL_VALUE_TYPE corresponding to sqrt(2).  */
 
 const REAL_VALUE_TYPE *
@@ -4878,7 +4861,7 @@  real_powi (REAL_VALUE_TYPE *r, machine_mode mode,
 
   if (n == 0)
     {
-      *r = dconst1;
+      *r = dconst<1> ();
       return false;
     }
   else if (n < 0)
@@ -4906,7 +4889,7 @@  real_powi (REAL_VALUE_TYPE *r, machine_mode mode,
     }
 
   if (neg)
-    inexact |= do_divide (&t, &dconst1, &t);
+    inexact |= do_divide (&t, &dconst<1> (), &t);
 
   real_convert (r, mode, &t);
   return inexact;
@@ -4935,7 +4918,7 @@  real_floor (REAL_VALUE_TYPE *r, machine_mode mode,
 
   do_fix_trunc (&t, x);
   if (! real_identical (&t, x) && x->sign)
-    do_add (&t, &t, &dconstm1, 0);
+    do_add (&t, &t, &dconst<-1> (), 0);
   if (mode != VOIDmode)
     real_convert (r, mode, &t);
   else
@@ -4953,7 +4936,7 @@  real_ceil (REAL_VALUE_TYPE *r, machine_mode mode,
 
   do_fix_trunc (&t, x);
   if (! real_identical (&t, x) && ! x->sign)
-    do_add (&t, &t, &dconst1, 0);
+    do_add (&t, &t, &dconst<1> (), 0);
   if (mode != VOIDmode)
     real_convert (r, mode, &t);
   else
@@ -4967,7 +4950,7 @@  void
 real_round (REAL_VALUE_TYPE *r, machine_mode mode,
 	    const REAL_VALUE_TYPE *x)
 {
-  do_add (r, x, &dconsthalf, x->sign);
+  do_add (r, x, &dconst<1, 2> (), x->sign);
   do_fix_trunc (r, r);
   if (mode != VOIDmode)
     real_convert (r, mode, r);
diff --git a/gcc/real.h b/gcc/real.h
index 1497279..72e1a04 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -403,22 +403,12 @@  extern void real_ldexp (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int);
 
 /* Constant real values 0, 1, 2, -1 and 0.5.  */
 
-extern REAL_VALUE_TYPE dconst0;
-extern REAL_VALUE_TYPE dconst1;
-extern REAL_VALUE_TYPE dconst2;
-extern REAL_VALUE_TYPE dconstm1;
-extern REAL_VALUE_TYPE dconsthalf;
-
-#define dconst_e()  (*dconst_e_ptr ())
-#define dconst_third()  (*dconst_third_ptr ())
-#define dconst_sqrt2()  (*dconst_sqrt2_ptr ())
+#define dconst_e() (*dconst_e_ptr ())
+#define dconst_sqrt2() (*dconst_sqrt2_ptr ())
 
 /* Function to return the real value special constant 'e'.  */
 extern const REAL_VALUE_TYPE * dconst_e_ptr (void);
 
-/* Returns the special REAL_VALUE_TYPE corresponding to 1/3.  */
-extern const REAL_VALUE_TYPE * dconst_third_ptr (void);
-
 /* Returns the special REAL_VALUE_TYPE corresponding to sqrt(2).  */
 extern const REAL_VALUE_TYPE * dconst_sqrt2_ptr (void);
 
@@ -473,6 +463,26 @@  extern void get_max_float (const struct real_format *, char *, size_t);
 extern wide_int real_to_integer (const REAL_VALUE_TYPE *, bool *, int);
 extern void real_from_integer (REAL_VALUE_TYPE *, machine_mode,
 			       const wide_int_ref &, signop);
+extern void real_from_fraction (REAL_VALUE_TYPE *, int, int);
+
+/* Return a constant A/B, in maximum precision.  */
+template<int a, int b>
+inline const REAL_VALUE_TYPE &
+dconst (void)
+{
+  static REAL_VALUE_TYPE value;
+  if (value.cl == rvc_zero)
+    real_from_fraction (&value, a, b);
+  return value;
+}
+
+/* Return a real for integer constant A.  */
+template<int a>
+inline const REAL_VALUE_TYPE &
+dconst (void)
+{
+  return dconst<a, 1> ();
+}
 #endif
 
 #endif /* ! GCC_REAL_H */
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 1f91afc..2e0afdd 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -2464,11 +2464,11 @@  simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
 	{
 	  const REAL_VALUE_TYPE *d1 = CONST_DOUBLE_REAL_VALUE (trueop1);
 
-	  if (real_equal (d1, &dconst2))
+	  if (real_equal (d1, &dconst<2> ()))
 	    return simplify_gen_binary (PLUS, mode, op0, copy_rtx (op0));
 
 	  if (!HONOR_SNANS (mode)
-	      && real_equal (d1, &dconstm1))
+	      && real_equal (d1, &dconst<-1> ()))
 	    return simplify_gen_unary (NEG, mode, op0, mode);
 	}
 
@@ -3093,17 +3093,17 @@  simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
 	      const REAL_VALUE_TYPE *d1 = CONST_DOUBLE_REAL_VALUE (trueop1);
 
 	      /* x/-1.0 is -x.  */
-	      if (real_equal (d1, &dconstm1)
+	      if (real_equal (d1, &dconst<-1> ())
 		  && !HONOR_SNANS (mode))
 		return simplify_gen_unary (NEG, mode, op0, mode);
 
 	      /* Change FP division by a constant into multiplication.
 		 Only do this with -freciprocal-math.  */
 	      if (flag_reciprocal_math
-		  && !real_equal (d1, &dconst0))
+		  && !real_equal (d1, &dconst<0> ()))
 		{
 		  REAL_VALUE_TYPE d;
-		  real_arithmetic (&d, RDIV_EXPR, &dconst1, d1);
+		  real_arithmetic (&d, RDIV_EXPR, &dconst<1> (), d1);
 		  tem = const_double_from_real_value (d, mode);
 		  return simplify_gen_binary (MULT, mode, op0, tem);
 		}
@@ -3862,7 +3862,7 @@  simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
 	    return 0;
 
 	  if (code == DIV
-	      && real_equal (&f1, &dconst0)
+	      && real_equal (&f1, &dconst<0> ())
 	      && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode)))
 	    return 0;
 
@@ -3895,9 +3895,9 @@  simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
 
 	  if (code == MULT && MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode)
 	      && flag_trapping_math
-	      && ((REAL_VALUE_ISINF (f0) && real_equal (&f1, &dconst0))
+	      && ((REAL_VALUE_ISINF (f0) && real_equal (&f1, &dconst<0> ()))
 		  || (REAL_VALUE_ISINF (f1)
-		      && real_equal (&f0, &dconst0))))
+		      && real_equal (&f0, &dconst<0> ()))))
 	    /* Inf * 0 = NaN plus exception.  */
 	    return 0;
 
diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c
index 112a325..640e7e5 100644
--- a/gcc/tree-call-cdce.c
+++ b/gcc/tree-call-cdce.c
@@ -199,9 +199,9 @@  check_pow (gcall *pow_call)
       /* Only handle a fixed range of constant.  */
       REAL_VALUE_TYPE mv;
       REAL_VALUE_TYPE bcv = TREE_REAL_CST (base);
-      if (real_equal (&bcv, &dconst1))
+      if (real_equal (&bcv, &dconst<1> ()))
         return false;
-      if (real_less (&bcv, &dconst1))
+      if (real_less (&bcv, &dconst<1> ()))
         return false;
       real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, UNSIGNED);
       if (real_less (&mv, &bcv))
@@ -420,8 +420,8 @@  gen_conditions_for_pow_cst_base (tree base, tree expn,
      sure it is consistent with check_pow.  */
   REAL_VALUE_TYPE mv;
   REAL_VALUE_TYPE bcv = TREE_REAL_CST (base);
-  gcc_assert (!real_equal (&bcv, &dconst1)
-              && !real_less (&bcv, &dconst1));
+  gcc_assert (!real_equal (&bcv, &dconst<1> ())
+	      && !real_less (&bcv, &dconst<1> ()));
   real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, UNSIGNED);
   gcc_assert (!real_less (&mv, &bcv));
 
diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c
index 649c9fe..4a67eb5 100644
--- a/gcc/tree-chrec.c
+++ b/gcc/tree-chrec.c
@@ -132,7 +132,7 @@  chrec_fold_plus_poly_poly (enum tree_code code,
 	   chrec_fold_minus (type, poly0, CHREC_LEFT (poly1)),
 	   chrec_fold_multiply (type, CHREC_RIGHT (poly1),
 				SCALAR_FLOAT_TYPE_P (type)
-				? build_real (type, dconstm1)
+				? build_real (type, dconst<-1> ())
 				: build_int_cst_type (type, -1)));
     }
 
@@ -233,7 +233,7 @@  chrec_fold_multiply_poly_poly (tree type,
   t1 = chrec_fold_plus (type, t1, t2);
   /* "2*b*d".  */
   t2 = chrec_fold_multiply (type, SCALAR_FLOAT_TYPE_P (type)
-			    ? build_real (type, dconst2)
+			    ? build_real (type, dconst<2> ())
 			    : build_int_cst (type, 2), t2);
 
   var = CHREC_VARIABLE (poly0);
@@ -326,7 +326,7 @@  chrec_fold_plus_1 (enum tree_code code, tree type,
 	       chrec_fold_minus (type, op0, CHREC_LEFT (op1)),
 	       chrec_fold_multiply (type, CHREC_RIGHT (op1),
 				    SCALAR_FLOAT_TYPE_P (type)
-				    ? build_real (type, dconstm1)
+				    ? build_real (type, dconst<-1> ())
 				    : build_int_cst_type (type, -1)));
 
 	CASE_CONVERT:
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index 93c0a54..2dce4dc 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -118,7 +118,7 @@  some_nonzerop (tree t)
      cannot be treated the same as operations with a real or imaginary
      operand if we care about the signs of zeros in the result.  */
   if (TREE_CODE (t) == REAL_CST && !flag_signed_zeros)
-    zerop = real_identical (&TREE_REAL_CST (t), &dconst0);
+    zerop = real_identical (&TREE_REAL_CST (t), &dconst<0> ());
   else if (TREE_CODE (t) == FIXED_CST)
     zerop = fixed_zerop (t);
   else if (TREE_CODE (t) == INTEGER_CST)
@@ -495,7 +495,7 @@  get_component_ssa_name (tree ssa_name, bool imag_p)
     {
       tree inner_type = TREE_TYPE (TREE_TYPE (ssa_name));
       if (SCALAR_FLOAT_TYPE_P (inner_type))
-	return build_real (inner_type, dconst0);
+	return build_real (inner_type, dconst<0> ());
       else
 	return build_int_cst (inner_type, 0);
     }
@@ -1021,7 +1021,7 @@  expand_complex_multiplication (gimple_stmt_iterator *gsi, tree inner_type,
     case PAIR (ONLY_IMAG, ONLY_REAL):
       rr = ar;
       if (TREE_CODE (ai) == REAL_CST
-	  && real_identical (&TREE_REAL_CST (ai), &dconst1))
+	  && real_identical (&TREE_REAL_CST (ai), &dconst<1> ()))
 	ri = br;
       else
 	ri = gimplify_build2 (gsi, MULT_EXPR, inner_type, ai, br);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 9b525f3..0758895 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -4094,7 +4094,7 @@  estimate_num_insns (gimple *stmt, eni_weights *weights)
 		      if (TREE_CODE (gimple_call_arg (stmt, 1)) == REAL_CST
 			  && (real_equal
 			      (&TREE_REAL_CST (gimple_call_arg (stmt, 1)),
-			       &dconst2)))
+			       &dconst<2> ())))
 			return estimate_operator_cost
 			    (MULT_EXPR, weights, gimple_call_arg (stmt, 0),
 			     gimple_call_arg (stmt, 0));
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index 0753bf3..e3f94fa 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -638,7 +638,7 @@  add_to_evolution_1 (unsigned loop_nb, tree chrec_before, tree to_add,
 	      var = loop_nb;
 	      left = chrec_before;
 	      right = SCALAR_FLOAT_TYPE_P (type)
-		? build_real (type, dconst0)
+		? build_real (type, dconst<0> ())
 		: build_int_cst (type, 0);
 	    }
 	  else
@@ -840,7 +840,7 @@  add_to_evolution (unsigned loop_nb, tree chrec_before, enum tree_code code,
 
   if (code == MINUS_EXPR)
     to_add = chrec_fold_multiply (type, to_add, SCALAR_FLOAT_TYPE_P (type)
-				  ? build_real (type, dconstm1)
+				  ? build_real (type, dconst<-1> ())
 				  : build_int_cst_type (type, -1));
 
   res = add_to_evolution_1 (loop_nb, chrec_before, to_add, at_stmt);
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index c226da5..5919c84 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -1158,7 +1158,7 @@  record_equality (tree x, tree y, class const_and_copies *const_and_copies)
      nonzero.  */
   if (HONOR_SIGNED_ZEROS (x)
       && (TREE_CODE (y) != REAL_CST
-	  || real_equal (&dconst0, &TREE_REAL_CST (y))))
+	  || real_equal (&dconst<0> (), &TREE_REAL_CST (y))))
     return;
 
   const_and_copies->record_const_or_copy (x, y, prev_x);
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 39c027c..288daef 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -1003,7 +1003,7 @@  powi_as_mults (gimple_stmt_iterator *gsi, location_t loc,
   tree target;
 
   if (n == 0)
-    return build_real (type, dconst1);
+    return build_real (type, dconst<1> ());
 
   memset (cache, 0,  sizeof (cache));
   cache[1] = arg0;
@@ -1015,7 +1015,7 @@  powi_as_mults (gimple_stmt_iterator *gsi, location_t loc,
   /* If the original exponent was negative, reciprocate the result.  */
   target = make_temp_ssa_name (type, NULL, "powmult");
   div_stmt = gimple_build_assign (target, RDIV_EXPR,
-				  build_real (type, dconst1), result);
+				  build_real (type, dconst<1> ()), result);
   gimple_set_location (div_stmt, loc);
   gsi_insert_before (gsi, div_stmt, GSI_SAME_STMT);
 
@@ -1128,7 +1128,7 @@  bool
 representable_as_half_series_p (REAL_VALUE_TYPE c, unsigned n,
 				 struct pow_synth_sqrt_info *info)
 {
-  REAL_VALUE_TYPE factor = dconsthalf;
+  REAL_VALUE_TYPE factor = dconst<1, 2> ();
   REAL_VALUE_TYPE remainder = c;
 
   info->deepest = 0;
@@ -1145,7 +1145,7 @@  representable_as_half_series_p (REAL_VALUE_TYPE c, unsigned n,
 
       /* We have hit zero.  The number is representable as a sum
          of powers of 0.5.  */
-      if (real_equal (&res, &dconst0))
+      if (real_equal (&res, &dconst<0> ()))
 	{
 	  info->factors[i] = true;
 	  info->deepest = i + 1;
@@ -1160,7 +1160,7 @@  representable_as_half_series_p (REAL_VALUE_TYPE c, unsigned n,
       else
 	info->factors[i] = false;
 
-      real_arithmetic (&factor, MULT_EXPR, &factor, &dconsthalf);
+      real_arithmetic (&factor, MULT_EXPR, &factor, &dconst<1, 2> ());
     }
   return false;
 }
@@ -1320,8 +1320,8 @@  expand_pow_as_sqrts (gimple_stmt_iterator *gsi, location_t loc,
   real_arithmetic (&frac_part, MINUS_EXPR, &exp, &whole_part);
 
 
-  REAL_VALUE_TYPE ceil_whole = dconst0;
-  REAL_VALUE_TYPE ceil_fract = dconst0;
+  REAL_VALUE_TYPE ceil_whole = dconst<0> ();
+  REAL_VALUE_TYPE ceil_fract = dconst<0> ();
 
   if (neg_exp)
     {
@@ -1367,7 +1367,7 @@  expand_pow_as_sqrts (gimple_stmt_iterator *gsi, location_t loc,
 
   memset (cache, 0, (max_depth + 1) * sizeof (tree));
 
-  tree integer_res = n == 0 ? build_real (type, dconst1) : arg0;
+  tree integer_res = n == 0 ? build_real (type, dconst<1> ()) : arg0;
 
   /* Calculate the integer part of the exponent.  */
   if (n > 1)
@@ -1447,7 +1447,7 @@  expand_pow_as_sqrts (gimple_stmt_iterator *gsi, location_t loc,
 	    res = fract_res;
 
 	  res = build_and_insert_binop (gsi, loc, "powrootrecip", RDIV_EXPR,
-					  build_real (type, dconst1), res);
+					build_real (type, dconst<1> ()), res);
 	}
       else
 	{
@@ -1470,17 +1470,13 @@  static tree
 gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc, 
 			   tree arg0, tree arg1)
 {
-  REAL_VALUE_TYPE c, cint, dconst1_3, dconst1_4, dconst1_6;
-  REAL_VALUE_TYPE c2, dconst3;
+  REAL_VALUE_TYPE c, c2, cint, dconst1_3, dconst1_6;
   HOST_WIDE_INT n;
   tree type, sqrtfn, cbrtfn, sqrt_arg0, result, cbrt_x, powi_cbrt_x;
   machine_mode mode;
   bool speed_p = optimize_bb_for_speed_p (gsi_bb (*gsi));
   bool hw_sqrt_exists, c_is_int, c2_is_int;
 
-  dconst1_4 = dconst1;
-  SET_REAL_EXP (&dconst1_4, REAL_EXP (&dconst1_4) - 2);
-
   /* If the exponent isn't a constant, there's nothing of interest
      to be done.  */
   if (TREE_CODE (arg1) != REAL_CST)
@@ -1509,7 +1505,7 @@  gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
      unless signed zeros must be maintained.  pow(-0,0.5) = +0, while
      sqrt(-0) = -0.  */
   if (sqrtfn
-      && real_equal (&c, &dconsthalf)
+      && real_equal (&c, &dconst<1, 2> ())
       && !HONOR_SIGNED_ZEROS (mode))
     return build_and_insert_call (gsi, loc, sqrtfn, arg0);
 
@@ -1522,7 +1518,7 @@  gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
      of 1./3. actually has an even denominator.  The correct value
      of cbrt(x) is a negative real value.  */
   cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
-  dconst1_3 = real_value_truncate (mode, dconst_third ());
+  dconst1_3 = real_value_truncate (mode, dconst<1, 3> ());
 
   if (flag_unsafe_math_optimizations
       && cbrtfn
@@ -1556,7 +1552,7 @@  gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
   if (flag_unsafe_math_optimizations
       && sqrtfn
       && hw_sqrt_exists
-      && (speed_p || real_equal (&c, &dconst1_4))
+      && (speed_p || real_equal (&c, &dconst<1, 4> ()))
       && !HONOR_SIGNED_ZEROS (mode))
     {
       unsigned int max_depth = speed_p
@@ -1570,7 +1566,7 @@  gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
 	return expand_with_sqrts;
     }
 
-  real_arithmetic (&c2, MULT_EXPR, &c, &dconst2);
+  real_arithmetic (&c2, MULT_EXPR, &c, &dconst<2> ());
   n = real_to_integer (&c2);
   real_from_integer (&cint, VOIDmode, n, SIGNED);
   c2_is_int = real_identical (&c2, &cint);
@@ -1584,12 +1580,11 @@  gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
      different from pow(x, 1./3.) due to rounding and behavior with
      negative x, we need to constrain this transformation to unsafe
      math and positive x or finite math.  */
-  real_from_integer (&dconst3, VOIDmode, 3, SIGNED);
-  real_arithmetic (&c2, MULT_EXPR, &c, &dconst3);
+  real_arithmetic (&c2, MULT_EXPR, &c, &dconst<3> ());
   real_round (&c2, mode, &c2);
   n = real_to_integer (&c2);
   real_from_integer (&cint, VOIDmode, n, SIGNED);
-  real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst3);
+  real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst<3> ());
   real_convert (&c2, mode, &c2);
 
   if (flag_unsafe_math_optimizations
@@ -1634,7 +1629,8 @@  gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc,
       /* If n is negative, reciprocate the result.  */
       if (n < 0)
 	result = build_and_insert_binop (gsi, loc, "powroot", RDIV_EXPR,
-					 build_real (type, dconst1), result);
+					 build_real (type, dconst<1> ()),
+					 result);
 
       return result;
     }
@@ -1793,8 +1789,8 @@  pass_cse_sincos::execute (function *fun)
 
 		      t0 = TREE_TYPE (arg0);
 		      t1 = TREE_TYPE (arg1);
-		      one = build_real (t0, dconst1);
-		      minus_one = build_real (t0, dconstm1);
+		      one = build_real (t0, dconst<1> ());
+		      minus_one = build_real (t0, dconst<-1> ());
 
 		      cond = make_temp_ssa_name (t1, NULL, "powi_cond");
 		      stmt = gimple_build_assign (cond, BIT_AND_EXPR,
@@ -3591,7 +3587,7 @@  pass_optimize_widening_mul::execute (function *fun)
 			if (TREE_CODE (gimple_call_arg (stmt, 1)) == REAL_CST
 			    && real_equal
 			         (&TREE_REAL_CST (gimple_call_arg (stmt, 1)),
-				  &dconst2)
+				  &dconst<2> ())
 			    && convert_mult_to_fma (stmt,
 						    gimple_call_arg (stmt, 0),
 						    gimple_call_arg (stmt, 0)))
diff --git a/gcc/tree-ssa-uncprop.c b/gcc/tree-ssa-uncprop.c
index 0f16c50..c247db7 100644
--- a/gcc/tree-ssa-uncprop.c
+++ b/gcc/tree-ssa-uncprop.c
@@ -153,7 +153,7 @@  associate_equivalences_with_edges (void)
 		     this value unless we know that the value is nonzero.  */
 		  if (HONOR_SIGNED_ZEROS (op0)
 		      && (TREE_CODE (op1) != REAL_CST
-			  || real_equal (&dconst0, &TREE_REAL_CST (op1))))
+			  || real_equal (&dconst<0> (), &TREE_REAL_CST (op1))))
 		    continue;
 
 		  equivalency = XNEW (struct edge_equivalency);
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 63e29aa..7d23428 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -3821,7 +3821,7 @@  get_initial_def_for_reduction (gimple *stmt, tree init_val,
   int i;
   bool nested_in_vect_loop = false;
   tree init_value;
-  REAL_VALUE_TYPE real_init_val = dconst0;
+  REAL_VALUE_TYPE real_init_val = dconst<0> ();
   int int_init_val = 0;
   gimple *def_stmt = NULL;
 
@@ -3886,7 +3886,7 @@  get_initial_def_for_reduction (gimple *stmt, tree init_val,
 
         if (code == MULT_EXPR)
           {
-            real_init_val = dconst1;
+            real_init_val = dconst<1> ();
             int_init_val = 1;
           }
 
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 48b5298..e78de75 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -1084,7 +1084,7 @@  vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
   if ((tree_fits_shwi_p (exp)
        && tree_to_shwi (exp) == 2)
       || (TREE_CODE (exp) == REAL_CST
-          && real_equal (&TREE_REAL_CST (exp), &dconst2)))
+	  && real_equal (&TREE_REAL_CST (exp), &dconst<2> ())))
     {
       *type_in = TREE_TYPE (base);
 
@@ -1095,7 +1095,7 @@  vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
 
   /* Catch square root.  */
   if (TREE_CODE (exp) == REAL_CST
-      && real_equal (&TREE_REAL_CST (exp), &dconsthalf))
+      && real_equal (&TREE_REAL_CST (exp), &dconst<1, 2> ()))
     {
       tree newfn = mathfn_built_in (TREE_TYPE (base), BUILT_IN_SQRT);
       *type_in = get_vectype_for_scalar_type (TREE_TYPE (base));
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 7a2d623..3b8e26b 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -2617,7 +2617,7 @@  vect_get_constant_vectors (tree op, slp_tree slp_node,
           case BIT_IOR_EXPR:
           case BIT_XOR_EXPR:
              if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (op)))
-               neutral_op = build_real (TREE_TYPE (op), dconst0);
+               neutral_op = build_real (TREE_TYPE (op), dconst<0> ());
              else
                neutral_op = build_int_cst (TREE_TYPE (op), 0);
 
@@ -2625,7 +2625,7 @@  vect_get_constant_vectors (tree op, slp_tree slp_node,
 
           case MULT_EXPR:
              if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (op)))
-               neutral_op = build_real (TREE_TYPE (op), dconst1);
+               neutral_op = build_real (TREE_TYPE (op), dconst<1> ());
              else
                neutral_op = build_int_cst (TREE_TYPE (op), 1);
 
diff --git a/gcc/tree.c b/gcc/tree.c
index f78a2c2..ef70b03 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1991,7 +1991,7 @@  build_one_cst (tree type)
       return build_int_cst (type, 1);
 
     case REAL_TYPE:
-      return build_real (type, dconst1);
+      return build_real (type, dconst<1> ());
 
     case FIXED_POINT_TYPE:
       /* We can only generate 1 for accum types.  */
@@ -2044,7 +2044,7 @@  build_minus_one_cst (tree type)
       return build_int_cst (type, -1);
 
     case REAL_TYPE:
-      return build_real (type, dconstm1);
+      return build_real (type, dconst<-1> ());
 
     case FIXED_POINT_TYPE:
       /* We can only generate 1 for accum types.  */
@@ -2084,7 +2084,7 @@  build_zero_cst (tree type)
       return build_int_cst (type, 0);
 
     case REAL_TYPE:
-      return build_real (type, dconst0);
+      return build_real (type, dconst<0> ());
 
     case FIXED_POINT_TYPE:
       return build_fixed (type, FCONST0 (TYPE_MODE (type)));
@@ -2554,7 +2554,7 @@  real_zerop (const_tree expr)
   switch (TREE_CODE (expr))
     {
     case REAL_CST:
-      return real_equal (&TREE_REAL_CST (expr), &dconst0)
+      return real_equal (&TREE_REAL_CST (expr), &dconst<0> ())
 	     && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
     case COMPLEX_CST:
       return real_zerop (TREE_REALPART (expr))
@@ -2584,7 +2584,7 @@  real_onep (const_tree expr)
   switch (TREE_CODE (expr))
     {
     case REAL_CST:
-      return real_equal (&TREE_REAL_CST (expr), &dconst1)
+      return real_equal (&TREE_REAL_CST (expr), &dconst<1> ())
 	     && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
     case COMPLEX_CST:
       return real_onep (TREE_REALPART (expr))
@@ -2613,7 +2613,7 @@  real_minus_onep (const_tree expr)
   switch (TREE_CODE (expr))
     {
     case REAL_CST:
-      return real_equal (&TREE_REAL_CST (expr), &dconstm1)
+      return real_equal (&TREE_REAL_CST (expr), &dconst<-1> ())
 	     && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
     case COMPLEX_CST:
       return real_minus_onep (TREE_REALPART (expr))
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index af586e3..fe2491c 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -1496,7 +1496,7 @@  ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
 	 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
 	 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
 	 either representable or infinity.  */
-      REAL_VALUE_TYPE maxval = dconst1;
+      REAL_VALUE_TYPE maxval = dconst<1> ();
       SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
       real_convert (&maxval, mode, &maxval);
       max = build_real (expr_type, maxval);
@@ -1508,10 +1508,10 @@  ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
 	{
 	  /* TYPE_MIN_VALUE is generally representable (or -inf),
 	     but TYPE_MIN_VALUE - 1.0 might not be.  */
-	  REAL_VALUE_TYPE minval = dconstm1, minval2;
+	  REAL_VALUE_TYPE minval = dconst<-1> (), minval2;
 	  SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
 	  real_convert (&minval, mode, &minval);
-	  real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
+	  real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst<1> ());
 	  real_convert (&minval2, mode, &minval2);
 	  if (real_compare (EQ_EXPR, &minval, &minval2)
 	      && !real_isinf (&minval))
@@ -1522,7 +1522,7 @@  ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
 		 of base digits, we want to subtract a number that
 		 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
 		 times smaller than minval.  */
-	      minval2 = dconst1;
+	      minval2 = dconst<1> ();
 	      gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
 	      SET_REAL_EXP (&minval2,
 			    REAL_EXP (&minval2) + prec - 1