]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/value-range.h
docs: Fix expected diagnostics URL [PR107599]
[thirdparty/gcc.git] / gcc / value-range.h
CommitLineData
cca78449 1/* Support routines for value ranges.
7adcbafe 2 Copyright (C) 2019-2022 Free Software Foundation, Inc.
4ba9fb0a
AH
3 Contributed by Aldy Hernandez <aldyh@redhat.com> and
4 Andrew Macleod <amacleod@redhat.com>.
cca78449
AH
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 3, or (at your option)
11any later version.
12
13GCC is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
22#ifndef GCC_VALUE_RANGE_H
23#define GCC_VALUE_RANGE_H
24
4f1bce19
AH
25class irange;
26
4ba9fb0a 27// Types of value ranges.
cca78449
AH
28enum value_range_kind
29{
30 /* Empty range. */
31 VR_UNDEFINED,
32 /* Range spans the entire domain. */
33 VR_VARYING,
34 /* Range is [MIN, MAX]. */
35 VR_RANGE,
36 /* Range is ~[MIN, MAX]. */
37 VR_ANTI_RANGE,
91746147
AH
38 /* Range is a NAN. */
39 VR_NAN,
cca78449
AH
40 /* Range is a nice guy. */
41 VR_LAST
42};
43
4f1bce19
AH
44// Discriminator between different vrange types.
45
46enum value_range_discriminator
47{
48 // Range holds an integer or pointer.
49 VR_IRANGE,
1a10bd84
AH
50 // Floating point range.
51 VR_FRANGE,
4f1bce19
AH
52 // Range holds an unsupported type.
53 VR_UNKNOWN
54};
55
56// Abstract class for ranges of any of the supported types.
a9058b08
AH
57//
58// To query what types ranger and the entire ecosystem can support,
59// use Value_Range::supports_type_p(tree type). This is a static
60// method available independently of any vrange object.
61//
62// To query what a given vrange variant can support, use:
63// irange::supports_p ()
64// frange::supports_p ()
65// etc
66//
67// To query what a range object can support, use:
68// void foo (vrange &v, irange &i, frange &f)
69// {
70// if (v.supports_type_p (type)) ...
71// if (i.supports_type_p (type)) ...
72// if (f.supports_type_p (type)) ...
73// }
4f1bce19
AH
74
75class vrange
76{
77 template <typename T> friend bool is_a (vrange &);
59c8e96d 78 friend class Value_Range;
4f1bce19 79public:
91a7f306 80 virtual void accept (const class vrange_visitor &v) const = 0;
89b0276d
AH
81 virtual void set (tree, tree, value_range_kind = VR_RANGE);
82 virtual tree type () const;
7e029e06 83 virtual bool supports_type_p (const_tree type) const;
89b0276d
AH
84 virtual void set_varying (tree type);
85 virtual void set_undefined ();
89b0276d
AH
86 virtual bool union_ (const vrange &);
87 virtual bool intersect (const vrange &);
4f1bce19
AH
88 virtual bool singleton_p (tree *result = NULL) const;
89 virtual bool contains_p (tree cst) const;
89b0276d
AH
90 virtual bool zero_p () const;
91 virtual bool nonzero_p () const;
92 virtual void set_nonzero (tree type);
93 virtual void set_zero (tree type);
94 virtual void set_nonnegative (tree type);
95 virtual bool fits_p (const vrange &r) const;
4f1bce19 96
4f1bce19
AH
97 bool varying_p () const;
98 bool undefined_p () const;
99 vrange& operator= (const vrange &);
100 bool operator== (const vrange &) const;
101 bool operator!= (const vrange &r) const { return !(*this == r); }
64864aa9 102 void dump (FILE *) const;
4f1bce19
AH
103
104 enum value_range_kind kind () const; // DEPRECATED
4f1bce19
AH
105
106protected:
107 ENUM_BITFIELD(value_range_kind) m_kind : 8;
108 ENUM_BITFIELD(value_range_discriminator) m_discriminator : 4;
109};
110
111// An integer range without any storage.
cca78449 112
4f1bce19 113class GTY((user)) irange : public vrange
cca78449 114{
d8474337 115 friend class vrange_allocator;
4e82205b 116 friend class irange_storage_slot; // For legacy_mode_p checks.
cca78449 117public:
4ba9fb0a 118 // In-place setters.
4f1bce19 119 virtual void set (tree, tree, value_range_kind = VR_RANGE) override;
1db05e1a
AH
120 void set (tree type, const wide_int_ref &, const wide_int_ref &,
121 value_range_kind = VR_RANGE);
4f1bce19
AH
122 virtual void set_nonzero (tree type) override;
123 virtual void set_zero (tree type) override;
124 virtual void set_nonnegative (tree type) override;
125 virtual void set_varying (tree type) override;
126 virtual void set_undefined () override;
cca78449 127
4ba9fb0a 128 // Range types.
7e029e06
AH
129 static bool supports_p (const_tree type);
130 virtual bool supports_type_p (const_tree type) const override;
4f1bce19 131 virtual tree type () const override;
cca78449 132
4ba9fb0a 133 // Iteration over sub-ranges.
cca78449
AH
134 unsigned num_pairs () const;
135 wide_int lower_bound (unsigned = 0) const;
136 wide_int upper_bound (unsigned) const;
137 wide_int upper_bound () const;
4ba9fb0a
AH
138
139 // Predicates.
4f1bce19
AH
140 virtual bool zero_p () const override;
141 virtual bool nonzero_p () const override;
142 virtual bool singleton_p (tree *result = NULL) const override;
143 virtual bool contains_p (tree cst) const override;
4ba9fb0a
AH
144
145 // In-place operators.
4f1bce19
AH
146 virtual bool union_ (const vrange &) override;
147 virtual bool intersect (const vrange &) override;
cca78449
AH
148 void invert ();
149
4ba9fb0a
AH
150 // Operator overloads.
151 irange& operator= (const irange &);
152 bool operator== (const irange &) const;
153 bool operator!= (const irange &r) const { return !(*this == r); }
154
155 // Misc methods.
4f1bce19 156 virtual bool fits_p (const vrange &r) const override;
91a7f306 157 virtual void accept (const vrange_visitor &v) const override;
4ba9fb0a 158
4e82205b
AH
159 // Nonzero masks.
160 wide_int get_nonzero_bits () const;
161 void set_nonzero_bits (const wide_int_ref &bits);
162
4ba9fb0a 163 // Deprecated legacy public methods.
4ba9fb0a
AH
164 tree min () const; // DEPRECATED
165 tree max () const; // DEPRECATED
166 bool symbolic_p () const; // DEPRECATED
167 bool constant_p () const; // DEPRECATED
168 void normalize_symbolics (); // DEPRECATED
169 void normalize_addresses (); // DEPRECATED
170 bool may_contain_p (tree) const; // DEPRECATED
f3204ce1 171 bool legacy_verbose_union_ (const class irange *); // DEPRECATED
1d3d7e88 172 bool legacy_verbose_intersect (const irange *); // DEPRECATED
4ba9fb0a 173
cca78449 174protected:
4ba9fb0a
AH
175 irange (tree *, unsigned);
176 // potential promotion to public?
177 tree tree_lower_bound (unsigned = 0) const;
178 tree tree_upper_bound (unsigned) const;
179 tree tree_upper_bound () const;
180
181 // In-place operators.
f3204ce1 182 bool irange_union (const irange &);
1d3d7e88 183 bool irange_intersect (const irange &);
4ba9fb0a
AH
184 void irange_set (tree, tree);
185 void irange_set_anti_range (tree, tree);
1d3d7e88 186 bool irange_contains_p (const irange &) const;
f3204ce1 187 bool irange_single_pair_union (const irange &r);
4ba9fb0a 188
dc80d5e8 189 void normalize_kind ();
4ba9fb0a
AH
190
191 bool legacy_mode_p () const;
192 bool legacy_equal_p (const irange &) const;
193 void legacy_union (irange *, const irange *);
194 void legacy_intersect (irange *, const irange *);
195 void verify_range ();
4ba9fb0a
AH
196 wide_int legacy_lower_bound (unsigned = 0) const;
197 wide_int legacy_upper_bound (unsigned) const;
198 int value_inside_range (tree) const;
199 bool maybe_anti_range () const;
5bcd7de6
AH
200 void copy_to_legacy (const irange &);
201 void copy_legacy_to_multi_range (const irange &);
cca78449
AH
202
203private:
3c658587
AH
204 friend void gt_ggc_mx (irange *);
205 friend void gt_pch_nx (irange *);
206 friend void gt_pch_nx (irange *, gt_pointer_operator, void *);
207
88081d38 208 void irange_set_1bit_anti_range (tree, tree);
dc80d5e8 209 bool varying_compatible_p () const;
4e82205b
AH
210 bool intersect_nonzero_bits (const irange &r);
211 bool union_nonzero_bits (const irange &r);
7df3693f
AH
212 wide_int get_nonzero_bits_from_range () const;
213 bool set_range_from_nonzero_bits ();
88081d38 214
1d3d7e88 215 bool intersect (const wide_int& lb, const wide_int& ub);
4ba9fb0a
AH
216 unsigned char m_num_ranges;
217 unsigned char m_max_ranges;
ffaf244c 218 tree m_nonzero_mask;
4ba9fb0a 219 tree *m_base;
cca78449
AH
220};
221
4ba9fb0a
AH
222// Here we describe an irange with N pairs of ranges. The storage for
223// the pairs is embedded in the class as an array.
224
225template<unsigned N>
226class GTY((user)) int_range : public irange
227{
228public:
229 int_range ();
230 int_range (tree, tree, value_range_kind = VR_RANGE);
231 int_range (tree type, const wide_int &, const wide_int &,
232 value_range_kind = VR_RANGE);
233 int_range (tree type);
234 int_range (const int_range &);
235 int_range (const irange &);
83bacf93 236 virtual ~int_range () = default;
4ba9fb0a
AH
237 int_range& operator= (const int_range &);
238private:
239 template <unsigned X> friend void gt_ggc_mx (int_range<X> *);
240 template <unsigned X> friend void gt_pch_nx (int_range<X> *);
241 template <unsigned X> friend void gt_pch_nx (int_range<X> *,
242 gt_pointer_operator, void *);
3c658587 243
e53b6e56 244 // ?? These stubs are for ipa-prop.cc which use a value_range in a
3c658587
AH
245 // hash_traits. hash-traits.h defines an extern of gt_ggc_mx (T &)
246 // instead of picking up the gt_ggc_mx (T *) version.
4ba9fb0a
AH
247 friend void gt_ggc_mx (int_range<1> *&);
248 friend void gt_pch_nx (int_range<1> *&);
249
250 tree m_ranges[N*2];
251};
252
4f1bce19 253// Unsupported temporaries may be created by ranger before it's known
89b0276d 254// they're unsupported, or by vr_values::get_value_range.
4f1bce19
AH
255
256class unsupported_range : public vrange
257{
258public:
47964e76
AH
259 unsupported_range ()
260 {
261 m_discriminator = VR_UNKNOWN;
262 set_undefined ();
263 }
264 virtual void set_undefined () final override
265 {
266 m_kind = VR_UNDEFINED;
267 }
91a7f306 268 virtual void accept (const vrange_visitor &v) const override;
4f1bce19
AH
269};
270
1a10bd84 271// A floating point range.
91746147
AH
272//
273// The representation is a type with a couple of endpoints, unioned
274// with the set of { -NAN, +Nan }.
1a10bd84
AH
275
276class frange : public vrange
277{
278 friend class frange_storage_slot;
67263231 279 friend class vrange_printer;
1a10bd84
AH
280public:
281 frange ();
282 frange (const frange &);
8bb1df03 283 frange (tree, tree, value_range_kind = VR_RANGE);
a901343a 284 frange (tree type);
8bb1df03
AH
285 frange (tree type, const REAL_VALUE_TYPE &min, const REAL_VALUE_TYPE &max,
286 value_range_kind = VR_RANGE);
7e029e06 287 static bool supports_p (const_tree type)
1a10bd84 288 {
b4d8a56a
AH
289 // ?? Decimal floats can have multiple representations for the
290 // same number. Supporting them may be as simple as just
291 // disabling them in singleton_p. No clue.
292 return SCALAR_FLOAT_TYPE_P (type) && !DECIMAL_FLOAT_TYPE_P (type);
1a10bd84
AH
293 }
294 virtual tree type () const override;
295 virtual void set (tree, tree, value_range_kind = VR_RANGE) override;
8bb1df03
AH
296 void set (tree type, const REAL_VALUE_TYPE &, const REAL_VALUE_TYPE &,
297 value_range_kind = VR_RANGE);
9c4c4186 298 void set_nan (tree type);
91746147 299 void set_nan (tree type, bool sign);
1a10bd84
AH
300 virtual void set_varying (tree type) override;
301 virtual void set_undefined () override;
302 virtual bool union_ (const vrange &) override;
303 virtual bool intersect (const vrange &) override;
8bb1df03
AH
304 virtual bool contains_p (tree) const override;
305 virtual bool singleton_p (tree *result = NULL) const override;
7e029e06 306 virtual bool supports_type_p (const_tree type) const override;
1a10bd84 307 virtual void accept (const vrange_visitor &v) const override;
048d3ad7
ML
308 virtual bool zero_p () const override;
309 virtual bool nonzero_p () const override;
310 virtual void set_nonzero (tree type) override;
311 virtual void set_zero (tree type) override;
cc95bca7 312 virtual void set_nonnegative (tree type) override;
1a10bd84
AH
313 frange& operator= (const frange &);
314 bool operator== (const frange &) const;
315 bool operator!= (const frange &r) const { return !(*this == r); }
8bb1df03
AH
316 const REAL_VALUE_TYPE &lower_bound () const;
317 const REAL_VALUE_TYPE &upper_bound () const;
91746147 318 void update_nan ();
10d6109f 319 void update_nan (bool sign);
6ce08237 320 void update_nan (tree) = delete; // Disallow silent conversion to bool.
91746147 321 void clear_nan ();
1a10bd84 322
67263231 323 // fpclassify like API
91746147
AH
324 bool known_isfinite () const;
325 bool known_isnan () const;
326 bool known_isinf () const;
327 bool maybe_isnan () const;
e23f7dab 328 bool maybe_isnan (bool sign) const;
91746147
AH
329 bool maybe_isinf () const;
330 bool signbit_p (bool &signbit) const;
658788f3 331 bool nan_signbit_p (bool &signbit) const;
1a10bd84
AH
332private:
333 void verify_range ();
3f056053 334 bool normalize_kind ();
91746147
AH
335 bool union_nans (const frange &);
336 bool intersect_nans (const frange &);
337 bool combine_zeros (const frange &, bool union_p);
2b61ed83 338 void flush_denormals_to_zero ();
1a10bd84 339
1a10bd84 340 tree m_type;
8bb1df03
AH
341 REAL_VALUE_TYPE m_min;
342 REAL_VALUE_TYPE m_max;
91746147
AH
343 bool m_pos_nan;
344 bool m_neg_nan;
1a10bd84
AH
345};
346
8bb1df03
AH
347inline const REAL_VALUE_TYPE &
348frange::lower_bound () const
349{
91746147 350 gcc_checking_assert (!undefined_p () && !known_isnan ());
8bb1df03
AH
351 return m_min;
352}
353
354inline const REAL_VALUE_TYPE &
355frange::upper_bound () const
356{
91746147 357 gcc_checking_assert (!undefined_p () && !known_isnan ());
8bb1df03
AH
358 return m_max;
359}
360
f4fa81ba 361// is_a<> and as_a<> implementation for vrange.
4f1bce19 362
f4fa81ba 363// Anything we haven't specialized is a hard fail.
4f1bce19
AH
364template <typename T>
365inline bool
f4fa81ba 366is_a (vrange &)
4f1bce19
AH
367{
368 gcc_unreachable ();
369 return false;
370}
371
372template <typename T>
373inline bool
374is_a (const vrange &v)
375{
376 // Reuse is_a <vrange> to implement the const version.
377 const T &derived = static_cast<const T &> (v);
378 return is_a <T> (const_cast<T &> (derived));
379}
380
381template <typename T>
382inline T &
383as_a (vrange &v)
384{
f4fa81ba
AH
385 gcc_checking_assert (is_a <T> (v));
386 return static_cast <T &> (v);
4f1bce19
AH
387}
388
389template <typename T>
390inline const T &
391as_a (const vrange &v)
392{
f4fa81ba
AH
393 gcc_checking_assert (is_a <T> (v));
394 return static_cast <const T &> (v);
4f1bce19
AH
395}
396
397// Specializations for the different range types.
398
399template <>
400inline bool
401is_a <irange> (vrange &v)
402{
403 return v.m_discriminator == VR_IRANGE;
404}
405
1a10bd84
AH
406template <>
407inline bool
408is_a <frange> (vrange &v)
409{
410 return v.m_discriminator == VR_FRANGE;
411}
412
91a7f306
AH
413class vrange_visitor
414{
415public:
416 virtual void visit (const irange &) const { }
1a10bd84 417 virtual void visit (const frange &) const { }
91a7f306
AH
418 virtual void visit (const unsupported_range &) const { }
419};
420
4ba9fb0a
AH
421// This is a special int_range<1> with only one pair, plus
422// VR_ANTI_RANGE magic to describe slightly more than can be described
423// in one pair. It is described in the code as a "legacy range" (as
424// opposed to multi-ranges which have multiple sub-ranges). It is
425// provided for backward compatibility with code that has not been
426// converted to multi-range irange's.
427//
428// There are copy operators to seamlessly copy to/fro multi-ranges.
429typedef int_range<1> value_range;
430
431// This is an "infinite" precision irange for use in temporary
432// calculations.
c5a6c223 433typedef int_range<255> int_range_max;
4ba9fb0a 434
59c8e96d
AH
435// This is an "infinite" precision range object for use in temporary
436// calculations for any of the handled types. The object can be
437// transparently used as a vrange.
438
439class Value_Range
440{
441public:
442 Value_Range ();
443 Value_Range (const vrange &r);
444 Value_Range (tree type);
0fd3c706 445 Value_Range (const Value_Range &);
59c8e96d
AH
446 void set_type (tree type);
447 vrange& operator= (const vrange &);
448 bool operator== (const Value_Range &r) const;
449 bool operator!= (const Value_Range &r) const;
450 operator vrange &();
451 operator const vrange &() const;
64864aa9 452 void dump (FILE *) const;
7e029e06 453 static bool supports_type_p (const_tree type);
59c8e96d
AH
454
455 // Convenience methods for vrange compatability.
456 void set (tree min, tree max, value_range_kind kind = VR_RANGE)
457 { return m_vrange->set (min, max, kind); }
458 tree type () { return m_vrange->type (); }
459 enum value_range_kind kind () { return m_vrange->kind (); }
460 bool varying_p () const { return m_vrange->varying_p (); }
461 bool undefined_p () const { return m_vrange->undefined_p (); }
462 void set_varying (tree type) { m_vrange->set_varying (type); }
463 void set_undefined () { m_vrange->set_undefined (); }
464 bool union_ (const vrange &r) { return m_vrange->union_ (r); }
465 bool intersect (const vrange &r) { return m_vrange->intersect (r); }
466 bool singleton_p (tree *result = NULL) const
467 { return m_vrange->singleton_p (result); }
468 bool zero_p () const { return m_vrange->zero_p (); }
469 wide_int lower_bound () const; // For irange/prange compatability.
470 wide_int upper_bound () const; // For irange/prange compatability.
91a7f306 471 void accept (const vrange_visitor &v) const { m_vrange->accept (v); }
59c8e96d
AH
472private:
473 void init (tree type);
89b0276d 474 unsupported_range m_unsupported;
59c8e96d
AH
475 vrange *m_vrange;
476 int_range_max m_irange;
1a10bd84 477 frange m_frange;
59c8e96d
AH
478};
479
480inline
481Value_Range::Value_Range ()
482{
483 m_vrange = &m_unsupported;
484}
485
486// Copy constructor from a vrange.
487
488inline
489Value_Range::Value_Range (const vrange &r)
490{
491 *this = r;
492}
493
494// Copy constructor from a TYPE. The range of the temporary is set to
495// UNDEFINED.
496
497inline
498Value_Range::Value_Range (tree type)
499{
500 init (type);
501}
502
0fd3c706
AH
503inline
504Value_Range::Value_Range (const Value_Range &r)
505{
506 m_vrange = r.m_vrange;
507}
508
59c8e96d
AH
509// Initialize object so it is possible to store temporaries of TYPE
510// into it.
511
512inline void
513Value_Range::init (tree type)
514{
515 gcc_checking_assert (TYPE_P (type));
516
a9058b08 517 if (irange::supports_p (type))
59c8e96d 518 m_vrange = &m_irange;
1a10bd84
AH
519 else if (frange::supports_p (type))
520 m_vrange = &m_frange;
59c8e96d
AH
521 else
522 m_vrange = &m_unsupported;
523}
524
525// Set the temporary to allow storing temporaries of TYPE. The range
526// of the temporary is set to UNDEFINED.
527
528inline void
529Value_Range::set_type (tree type)
530{
531 init (type);
532 m_vrange->set_undefined ();
533}
534
535// Assignment operator for temporaries. Copying incompatible types is
536// allowed.
537
538inline vrange &
539Value_Range::operator= (const vrange &r)
540{
541 if (is_a <irange> (r))
542 {
543 m_irange = as_a <irange> (r);
544 m_vrange = &m_irange;
545 }
1a10bd84
AH
546 else if (is_a <frange> (r))
547 {
548 m_frange = as_a <frange> (r);
549 m_vrange = &m_frange;
550 }
59c8e96d
AH
551 else
552 gcc_unreachable ();
553
554 return *m_vrange;
555}
556
557inline bool
558Value_Range::operator== (const Value_Range &r) const
559{
560 return *m_vrange == *r.m_vrange;
561}
562
563inline bool
564Value_Range::operator!= (const Value_Range &r) const
565{
566 return *m_vrange != *r.m_vrange;
567}
568
569inline
570Value_Range::operator vrange &()
571{
572 return *m_vrange;
573}
574
575inline
576Value_Range::operator const vrange &() const
577{
578 return *m_vrange;
579}
580
a9058b08
AH
581// Return TRUE if TYPE is supported by the vrange infrastructure.
582
583inline bool
7e029e06 584Value_Range::supports_type_p (const_tree type)
a9058b08 585{
1a10bd84 586 return irange::supports_p (type) || frange::supports_p (type);
a9058b08
AH
587}
588
4ba9fb0a
AH
589// Returns true for an old-school value_range as described above.
590inline bool
591irange::legacy_mode_p () const
592{
593 return m_max_ranges == 1;
594}
595
596extern bool range_has_numeric_bounds_p (const irange *);
cca78449
AH
597extern bool ranges_from_anti_range (const value_range *,
598 value_range *, value_range *);
4f1bce19 599extern void dump_value_range (FILE *, const vrange *);
cca78449
AH
600extern bool vrp_val_is_min (const_tree);
601extern bool vrp_val_is_max (const_tree);
cca78449 602extern bool vrp_operand_equal_p (const_tree, const_tree);
b7fd7fb5
AH
603inline REAL_VALUE_TYPE frange_val_min (const_tree type);
604inline REAL_VALUE_TYPE frange_val_max (const_tree type);
cca78449 605
4ba9fb0a 606inline value_range_kind
4f1bce19 607vrange::kind () const
4ba9fb0a 608{
dc80d5e8 609 return m_kind;
4ba9fb0a
AH
610}
611
612// Number of sub-ranges in a range.
613
614inline unsigned
615irange::num_pairs () const
cca78449 616{
db3581c4
AH
617 if (m_kind == VR_ANTI_RANGE)
618 return constant_p () ? 2 : 1;
4ba9fb0a 619 else
db3581c4 620 return m_num_ranges;
cca78449
AH
621}
622
4ba9fb0a
AH
623inline tree
624irange::type () const
625{
77803216 626 gcc_checking_assert (m_num_ranges > 0);
4ba9fb0a
AH
627 return TREE_TYPE (m_base[0]);
628}
629
630// Return the lower bound of a sub-range expressed as a tree. PAIR is
631// the sub-range in question.
632
633inline tree
634irange::tree_lower_bound (unsigned pair) const
635{
636 return m_base[pair * 2];
637}
638
639// Return the upper bound of a sub-range expressed as a tree. PAIR is
640// the sub-range in question.
641
642inline tree
643irange::tree_upper_bound (unsigned pair) const
cca78449 644{
4ba9fb0a 645 return m_base[pair * 2 + 1];
cca78449
AH
646}
647
4ba9fb0a
AH
648// Return the highest bound of a range expressed as a tree.
649
cca78449 650inline tree
4ba9fb0a 651irange::tree_upper_bound () const
cca78449 652{
4ba9fb0a
AH
653 gcc_checking_assert (m_num_ranges);
654 return tree_upper_bound (m_num_ranges - 1);
cca78449
AH
655}
656
657inline tree
4ba9fb0a 658irange::min () const
cca78449 659{
4ba9fb0a 660 return tree_lower_bound (0);
cca78449
AH
661}
662
663inline tree
4ba9fb0a 664irange::max () const
cca78449 665{
4ba9fb0a
AH
666 if (m_num_ranges)
667 return tree_upper_bound ();
668 else
669 return NULL;
cca78449
AH
670}
671
672inline bool
dc80d5e8 673irange::varying_compatible_p () const
cca78449 674{
4ba9fb0a
AH
675 if (m_num_ranges != 1)
676 return false;
677
678 tree l = m_base[0];
679 tree u = m_base[1];
680 tree t = TREE_TYPE (l);
dc80d5e8
AH
681
682 if (m_kind == VR_VARYING && t == error_mark_node)
683 return true;
684
3d3470e2
AH
685 unsigned prec = TYPE_PRECISION (t);
686 signop sign = TYPE_SIGN (t);
4ba9fb0a 687 if (INTEGRAL_TYPE_P (t))
3d3470e2 688 return (wi::to_wide (l) == wi::min_value (prec, sign)
c106825b 689 && wi::to_wide (u) == wi::max_value (prec, sign)
ffaf244c 690 && (!m_nonzero_mask || wi::to_wide (m_nonzero_mask) == -1));
4ba9fb0a 691 if (POINTER_TYPE_P (t))
3d3470e2 692 return (wi::to_wide (l) == 0
7df3693f 693 && wi::to_wide (u) == wi::max_value (prec, sign)
ffaf244c 694 && (!m_nonzero_mask || wi::to_wide (m_nonzero_mask) == -1));
4ba9fb0a 695 return true;
dc80d5e8 696}
4ba9fb0a 697
1db05e1a
AH
698inline void
699irange::set (tree type, const wide_int_ref &min, const wide_int_ref &max,
700 value_range_kind kind)
701{
702 set (wide_int_to_tree (type, min), wide_int_to_tree (type, max), kind);
703}
704
dc80d5e8 705inline bool
4f1bce19 706vrange::varying_p () const
dc80d5e8
AH
707{
708 return m_kind == VR_VARYING;
cca78449
AH
709}
710
711inline bool
4f1bce19 712vrange::undefined_p () const
cca78449
AH
713{
714 return m_kind == VR_UNDEFINED;
715}
716
717inline bool
4ba9fb0a 718irange::zero_p () const
cca78449 719{
4ba9fb0a
AH
720 return (m_kind == VR_RANGE && m_num_ranges == 1
721 && integer_zerop (tree_lower_bound (0))
722 && integer_zerop (tree_upper_bound (0)));
cca78449
AH
723}
724
725inline bool
4ba9fb0a 726irange::nonzero_p () const
cca78449 727{
4ba9fb0a
AH
728 if (undefined_p ())
729 return false;
cca78449 730
4ba9fb0a
AH
731 tree zero = build_zero_cst (type ());
732 return *this == int_range<1> (zero, zero, VR_ANTI_RANGE);
cca78449
AH
733}
734
735inline bool
7e029e06 736irange::supports_p (const_tree type)
cca78449 737{
59c8e96d 738 return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type);
cca78449
AH
739}
740
741inline bool
4ba9fb0a 742range_includes_zero_p (const irange *vr)
cca78449
AH
743{
744 if (vr->undefined_p ())
745 return false;
746
747 if (vr->varying_p ())
748 return true;
749
750 return vr->may_contain_p (build_zero_cst (vr->type ()));
751}
752
7b7bbbcf 753inline void
3c658587 754gt_ggc_mx (irange *x)
4ba9fb0a 755{
3c658587 756 for (unsigned i = 0; i < x->m_num_ranges; ++i)
4ba9fb0a 757 {
3c658587
AH
758 gt_ggc_mx (x->m_base[i * 2]);
759 gt_ggc_mx (x->m_base[i * 2 + 1]);
4ba9fb0a 760 }
ffaf244c
AH
761 if (x->m_nonzero_mask)
762 gt_ggc_mx (x->m_nonzero_mask);
4ba9fb0a
AH
763}
764
7b7bbbcf 765inline void
3c658587 766gt_pch_nx (irange *x)
4ba9fb0a 767{
3c658587 768 for (unsigned i = 0; i < x->m_num_ranges; ++i)
4ba9fb0a 769 {
3c658587
AH
770 gt_pch_nx (x->m_base[i * 2]);
771 gt_pch_nx (x->m_base[i * 2 + 1]);
4ba9fb0a 772 }
ffaf244c
AH
773 if (x->m_nonzero_mask)
774 gt_pch_nx (x->m_nonzero_mask);
4ba9fb0a
AH
775}
776
7b7bbbcf 777inline void
3c658587 778gt_pch_nx (irange *x, gt_pointer_operator op, void *cookie)
4ba9fb0a 779{
3c658587 780 for (unsigned i = 0; i < x->m_num_ranges; ++i)
4ba9fb0a 781 {
747380f4
JJ
782 op (&x->m_base[i * 2], NULL, cookie);
783 op (&x->m_base[i * 2 + 1], NULL, cookie);
4ba9fb0a 784 }
ffaf244c
AH
785 if (x->m_nonzero_mask)
786 op (&x->m_nonzero_mask, NULL, cookie);
4ba9fb0a
AH
787}
788
3c658587
AH
789template<unsigned N>
790inline void
791gt_ggc_mx (int_range<N> *x)
792{
793 gt_ggc_mx ((irange *) x);
794}
795
796template<unsigned N>
797inline void
798gt_pch_nx (int_range<N> *x)
799{
800 gt_pch_nx ((irange *) x);
801}
802
803template<unsigned N>
804inline void
805gt_pch_nx (int_range<N> *x, gt_pointer_operator op, void *cookie)
806{
807 gt_pch_nx ((irange *) x, op, cookie);
808}
809
4ba9fb0a
AH
810// Constructors for irange
811
812inline
813irange::irange (tree *base, unsigned nranges)
814{
4f1bce19 815 m_discriminator = VR_IRANGE;
4ba9fb0a 816 m_base = base;
4ba9fb0a 817 m_max_ranges = nranges;
17dea11c 818 set_undefined ();
4ba9fb0a
AH
819}
820
821// Constructors for int_range<>.
822
823template<unsigned N>
824inline
825int_range<N>::int_range ()
826 : irange (m_ranges, N)
827{
828}
829
830template<unsigned N>
831int_range<N>::int_range (const int_range &other)
832 : irange (m_ranges, N)
833{
834 irange::operator= (other);
835}
836
837template<unsigned N>
838int_range<N>::int_range (tree min, tree max, value_range_kind kind)
839 : irange (m_ranges, N)
840{
841 irange::set (min, max, kind);
842}
843
844template<unsigned N>
845int_range<N>::int_range (tree type)
846 : irange (m_ranges, N)
847{
848 set_varying (type);
849}
850
851template<unsigned N>
852int_range<N>::int_range (tree type, const wide_int &wmin, const wide_int &wmax,
853 value_range_kind kind)
854 : irange (m_ranges, N)
855{
856 tree min = wide_int_to_tree (type, wmin);
857 tree max = wide_int_to_tree (type, wmax);
858 set (min, max, kind);
859}
860
861template<unsigned N>
862int_range<N>::int_range (const irange &other)
863 : irange (m_ranges, N)
864{
865 irange::operator= (other);
866}
867
868template<unsigned N>
869int_range<N>&
870int_range<N>::operator= (const int_range &src)
871{
872 irange::operator= (src);
873 return *this;
874}
875
4ba9fb0a
AH
876inline void
877irange::set_undefined ()
878{
dc80d5e8 879 m_kind = VR_UNDEFINED;
4ba9fb0a 880 m_num_ranges = 0;
ffaf244c 881 m_nonzero_mask = NULL;
4ba9fb0a
AH
882}
883
884inline void
885irange::set_varying (tree type)
886{
dc80d5e8 887 m_kind = VR_VARYING;
4ba9fb0a 888 m_num_ranges = 1;
ffaf244c 889 m_nonzero_mask = NULL;
dc80d5e8 890
4ba9fb0a
AH
891 if (INTEGRAL_TYPE_P (type))
892 {
e828f4b5
AM
893 // Strict enum's require varying to be not TYPE_MIN/MAX, but rather
894 // min_value and max_value.
3d3470e2
AH
895 wide_int min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
896 wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
e828f4b5
AM
897 if (wi::eq_p (max, wi::to_wide (TYPE_MAX_VALUE (type)))
898 && wi::eq_p (min, wi::to_wide (TYPE_MIN_VALUE (type))))
899 {
900 m_base[0] = TYPE_MIN_VALUE (type);
901 m_base[1] = TYPE_MAX_VALUE (type);
902 }
903 else
904 {
905 m_base[0] = wide_int_to_tree (type, min);
906 m_base[1] = wide_int_to_tree (type, max);
907 }
4ba9fb0a
AH
908 }
909 else if (POINTER_TYPE_P (type))
910 {
911 m_base[0] = build_int_cst (type, 0);
912 m_base[1] = build_int_cst (type, -1);
913 }
914 else
915 m_base[0] = m_base[1] = error_mark_node;
916}
917
4ba9fb0a
AH
918// Return the lower bound of a sub-range. PAIR is the sub-range in
919// question.
920
921inline wide_int
922irange::lower_bound (unsigned pair) const
923{
924 if (legacy_mode_p ())
925 return legacy_lower_bound (pair);
77803216 926 gcc_checking_assert (m_num_ranges > 0);
4ba9fb0a
AH
927 gcc_checking_assert (pair + 1 <= num_pairs ());
928 return wi::to_wide (tree_lower_bound (pair));
929}
930
931// Return the upper bound of a sub-range. PAIR is the sub-range in
932// question.
933
934inline wide_int
935irange::upper_bound (unsigned pair) const
936{
937 if (legacy_mode_p ())
938 return legacy_upper_bound (pair);
77803216 939 gcc_checking_assert (m_num_ranges > 0);
4ba9fb0a
AH
940 gcc_checking_assert (pair + 1 <= num_pairs ());
941 return wi::to_wide (tree_upper_bound (pair));
942}
943
944// Return the highest bound of a range.
945
946inline wide_int
947irange::upper_bound () const
948{
949 unsigned pairs = num_pairs ();
950 gcc_checking_assert (pairs > 0);
951 return upper_bound (pairs - 1);
952}
953
f3204ce1 954inline bool
4f1bce19 955irange::union_ (const vrange &r)
4ba9fb0a
AH
956{
957 dump_flags_t m_flags = dump_flags;
958 dump_flags &= ~TDF_DETAILS;
4f1bce19 959 bool ret = irange::legacy_verbose_union_ (&as_a <irange> (r));
4ba9fb0a 960 dump_flags = m_flags;
f3204ce1 961 return ret;
4ba9fb0a
AH
962}
963
1d3d7e88 964inline bool
4f1bce19 965irange::intersect (const vrange &r)
4ba9fb0a
AH
966{
967 dump_flags_t m_flags = dump_flags;
968 dump_flags &= ~TDF_DETAILS;
4f1bce19 969 bool ret = irange::legacy_verbose_intersect (&as_a <irange> (r));
4ba9fb0a 970 dump_flags = m_flags;
1d3d7e88 971 return ret;
4ba9fb0a
AH
972}
973
974// Set value range VR to a nonzero range of type TYPE.
975
976inline void
977irange::set_nonzero (tree type)
978{
979 tree zero = build_int_cst (type, 0);
980 if (legacy_mode_p ())
981 set (zero, zero, VR_ANTI_RANGE);
982 else
983 irange_set_anti_range (zero, zero);
984}
985
986// Set value range VR to a ZERO range of type TYPE.
987
988inline void
989irange::set_zero (tree type)
990{
991 tree z = build_int_cst (type, 0);
992 if (legacy_mode_p ())
bbe836bc 993 set (z, z);
4ba9fb0a
AH
994 else
995 irange_set (z, z);
996}
997
4e85ad79 998// Normalize a range to VARYING or UNDEFINED if possible.
4ba9fb0a 999
4e85ad79 1000inline void
dc80d5e8
AH
1001irange::normalize_kind ()
1002{
1003 if (m_num_ranges == 0)
4e82205b 1004 set_undefined ();
dc80d5e8 1005 else if (varying_compatible_p ())
4ba9fb0a 1006 {
4e85ad79 1007 if (m_kind == VR_RANGE)
dc80d5e8 1008 m_kind = VR_VARYING;
4e85ad79 1009 else if (m_kind == VR_ANTI_RANGE)
4ba9fb0a 1010 set_undefined ();
4ba9fb0a 1011 }
4ba9fb0a
AH
1012}
1013
3f056053
AH
1014// Return the maximum value for TYPE.
1015
1016inline tree
1017vrp_val_max (const_tree type)
1018{
1019 if (INTEGRAL_TYPE_P (type))
1020 return TYPE_MAX_VALUE (type);
1021 if (POINTER_TYPE_P (type))
1022 {
1023 wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
1024 return wide_int_to_tree (const_cast<tree> (type), max);
1025 }
1026 if (frange::supports_p (type))
b7fd7fb5
AH
1027 {
1028 REAL_VALUE_TYPE r = frange_val_max (type);
1029 return build_real (const_cast <tree> (type), r);
1030 }
3f056053
AH
1031 return NULL_TREE;
1032}
1033
1034// Return the minimum value for TYPE.
1035
1036inline tree
1037vrp_val_min (const_tree type)
1038{
1039 if (INTEGRAL_TYPE_P (type))
1040 return TYPE_MIN_VALUE (type);
1041 if (POINTER_TYPE_P (type))
1042 return build_zero_cst (const_cast<tree> (type));
1043 if (frange::supports_p (type))
b7fd7fb5
AH
1044 {
1045 REAL_VALUE_TYPE r = frange_val_min (type);
1046 return build_real (const_cast <tree> (type), r);
1047 }
3f056053
AH
1048 return NULL_TREE;
1049}
1a10bd84 1050
1a10bd84
AH
1051inline
1052frange::frange ()
1053{
1054 m_discriminator = VR_FRANGE;
1a10bd84
AH
1055 set_undefined ();
1056}
1057
1058inline
1059frange::frange (const frange &src)
1060{
1061 m_discriminator = VR_FRANGE;
1062 *this = src;
1063}
1064
a901343a
AH
1065inline
1066frange::frange (tree type)
1067{
1068 m_discriminator = VR_FRANGE;
1069 set_varying (type);
1070}
1071
8bb1df03
AH
1072// frange constructor from REAL_VALUE_TYPE endpoints.
1073
1074inline
1075frange::frange (tree type,
1076 const REAL_VALUE_TYPE &min, const REAL_VALUE_TYPE &max,
1077 value_range_kind kind)
1078{
1079 m_discriminator = VR_FRANGE;
1080 set (type, min, max, kind);
1081}
1082
1083// frange constructor from trees.
1084
1085inline
1086frange::frange (tree min, tree max, value_range_kind kind)
1087{
1088 m_discriminator = VR_FRANGE;
1089 set (min, max, kind);
1090}
1091
1a10bd84
AH
1092inline tree
1093frange::type () const
1094{
6da65479 1095 gcc_checking_assert (!undefined_p ());
1a10bd84
AH
1096 return m_type;
1097}
1098
1099inline void
1100frange::set_varying (tree type)
1101{
1102 m_kind = VR_VARYING;
1103 m_type = type;
b7fd7fb5
AH
1104 m_min = frange_val_min (type);
1105 m_max = frange_val_max (type);
f4fda3ee
AH
1106 if (HONOR_NANS (m_type))
1107 {
1108 m_pos_nan = true;
1109 m_neg_nan = true;
1110 }
1111 else
1112 {
1113 m_pos_nan = false;
1114 m_neg_nan = false;
1115 }
1a10bd84
AH
1116}
1117
1118inline void
1119frange::set_undefined ()
1120{
1121 m_kind = VR_UNDEFINED;
324fa420
AH
1122 m_type = NULL;
1123 m_pos_nan = false;
1124 m_neg_nan = false;
1125 // m_min and m_min are unitialized as they are REAL_VALUE_TYPE ??.
91746147
AH
1126 if (flag_checking)
1127 verify_range ();
1128}
1129
1130// Set the NAN bit and adjust the range.
1131
1132inline void
1133frange::update_nan ()
1134{
1135 gcc_checking_assert (!undefined_p ());
e9d50e7a
AH
1136 if (HONOR_NANS (m_type))
1137 {
1138 m_pos_nan = true;
1139 m_neg_nan = true;
1140 normalize_kind ();
1141 if (flag_checking)
1142 verify_range ();
1143 }
91746147
AH
1144}
1145
10d6109f
AH
1146// Like above, but set the sign of the NAN.
1147
1148inline void
1149frange::update_nan (bool sign)
1150{
1151 gcc_checking_assert (!undefined_p ());
e9d50e7a
AH
1152 if (HONOR_NANS (m_type))
1153 {
1154 m_pos_nan = !sign;
1155 m_neg_nan = sign;
1156 normalize_kind ();
1157 if (flag_checking)
1158 verify_range ();
1159 }
10d6109f
AH
1160}
1161
91746147
AH
1162// Clear the NAN bit and adjust the range.
1163
1164inline void
1165frange::clear_nan ()
1166{
1167 gcc_checking_assert (!undefined_p ());
1168 m_pos_nan = false;
1169 m_neg_nan = false;
1170 normalize_kind ();
1171 if (flag_checking)
1172 verify_range ();
8bb1df03
AH
1173}
1174
1175// Set R to maximum representable value for TYPE.
1176
b7fd7fb5
AH
1177inline REAL_VALUE_TYPE
1178real_max_representable (const_tree type)
8bb1df03 1179{
b7fd7fb5 1180 REAL_VALUE_TYPE r;
8bb1df03
AH
1181 char buf[128];
1182 get_max_float (REAL_MODE_FORMAT (TYPE_MODE (type)),
1183 buf, sizeof (buf), false);
b7fd7fb5 1184 int res = real_from_string (&r, buf);
8bb1df03 1185 gcc_checking_assert (!res);
b7fd7fb5 1186 return r;
8bb1df03
AH
1187}
1188
b7fd7fb5 1189// Return the minimum representable value for TYPE.
8bb1df03 1190
b7fd7fb5
AH
1191inline REAL_VALUE_TYPE
1192real_min_representable (const_tree type)
1193{
1194 REAL_VALUE_TYPE r = real_max_representable (type);
1195 r = real_value_negate (&r);
1196 return r;
1197}
1198
1199// Return the minimum value for TYPE.
1200
1201inline REAL_VALUE_TYPE
1202frange_val_min (const_tree type)
1203{
82866f43 1204 if (HONOR_INFINITIES (type))
b7fd7fb5 1205 return dconstninf;
82866f43
AH
1206 else
1207 return real_min_representable (type);
b7fd7fb5
AH
1208}
1209
1210// Return the maximum value for TYPE.
1211
1212inline REAL_VALUE_TYPE
1213frange_val_max (const_tree type)
1214{
82866f43 1215 if (HONOR_INFINITIES (type))
b7fd7fb5 1216 return dconstinf;
82866f43
AH
1217 else
1218 return real_max_representable (type);
b7fd7fb5
AH
1219}
1220
1221// Return TRUE if R is the minimum value for TYPE.
1222
1223inline bool
1224frange_val_is_min (const REAL_VALUE_TYPE &r, const_tree type)
1225{
1226 REAL_VALUE_TYPE min = frange_val_min (type);
1227 return real_identical (&min, &r);
1228}
1229
1230// Return TRUE if R is the max value for TYPE.
1231
1232inline bool
1233frange_val_is_max (const REAL_VALUE_TYPE &r, const_tree type)
8bb1df03 1234{
b7fd7fb5
AH
1235 REAL_VALUE_TYPE max = frange_val_max (type);
1236 return real_identical (&max, &r);
1a10bd84
AH
1237}
1238
91746147 1239// Build a signless NAN of type TYPE.
7e3f1843 1240
9c4c4186
AH
1241inline void
1242frange::set_nan (tree type)
7e3f1843 1243{
e9d50e7a
AH
1244 if (HONOR_NANS (type))
1245 {
1246 m_kind = VR_NAN;
1247 m_type = type;
1248 m_pos_nan = true;
1249 m_neg_nan = true;
1250 if (flag_checking)
1251 verify_range ();
1252 }
1253 else
1254 set_undefined ();
91746147
AH
1255}
1256
1257// Build a NAN of type TYPE with SIGN.
1258
1259inline void
1260frange::set_nan (tree type, bool sign)
1261{
e9d50e7a
AH
1262 if (HONOR_NANS (type))
1263 {
1264 m_kind = VR_NAN;
1265 m_type = type;
1266 m_neg_nan = sign;
1267 m_pos_nan = !sign;
1268 if (flag_checking)
1269 verify_range ();
1270 }
1271 else
1272 set_undefined ();
7e3f1843
AH
1273}
1274
67263231
AH
1275// Return TRUE if range is known to be finite.
1276
1277inline bool
91746147 1278frange::known_isfinite () const
67263231
AH
1279{
1280 if (undefined_p () || varying_p () || m_kind == VR_ANTI_RANGE)
1281 return false;
91746147 1282 return (!maybe_isnan () && !real_isinf (&m_min) && !real_isinf (&m_max));
67263231
AH
1283}
1284
1285// Return TRUE if range may be infinite.
1286
1287inline bool
91746147 1288frange::maybe_isinf () const
67263231 1289{
91746147 1290 if (undefined_p () || m_kind == VR_ANTI_RANGE || m_kind == VR_NAN)
67263231
AH
1291 return false;
1292 if (varying_p ())
1293 return true;
1294 return real_isinf (&m_min) || real_isinf (&m_max);
1295}
1296
1297// Return TRUE if range is known to be the [-INF,-INF] or [+INF,+INF].
1298
1299inline bool
91746147 1300frange::known_isinf () const
67263231
AH
1301{
1302 return (m_kind == VR_RANGE
1303 && real_identical (&m_min, &m_max)
1304 && real_isinf (&m_min));
1305}
1306
1307// Return TRUE if range is possibly a NAN.
1308
1309inline bool
91746147 1310frange::maybe_isnan () const
67263231 1311{
2438b6a4
AH
1312 if (undefined_p ())
1313 return false;
91746147 1314 return m_pos_nan || m_neg_nan;
67263231
AH
1315}
1316
e23f7dab
AH
1317// Return TRUE if range is possibly a NAN with SIGN.
1318
1319inline bool
1320frange::maybe_isnan (bool sign) const
1321{
1322 if (undefined_p ())
1323 return false;
1324 if (sign)
1325 return m_neg_nan;
1326 return m_pos_nan;
1327}
1328
67263231
AH
1329// Return TRUE if range is a +NAN or -NAN.
1330
1331inline bool
91746147 1332frange::known_isnan () const
67263231 1333{
91746147 1334 return m_kind == VR_NAN;
67263231
AH
1335}
1336
1337// If the signbit for the range is known, set it in SIGNBIT and return
1338// TRUE.
1339
1340inline bool
91746147 1341frange::signbit_p (bool &signbit) const
67263231 1342{
91746147 1343 if (undefined_p ())
67263231 1344 return false;
91746147
AH
1345
1346 // NAN with unknown sign.
1347 if (m_pos_nan && m_neg_nan)
67263231 1348 return false;
91746147
AH
1349 // No NAN.
1350 if (!m_pos_nan && !m_neg_nan)
1351 {
1352 if (m_min.sign == m_max.sign)
1353 {
1354 signbit = m_min.sign;
1355 return true;
1356 }
1357 return false;
1358 }
1359 // NAN with known sign.
1360 bool nan_sign = m_neg_nan;
1361 if (known_isnan ()
1362 || (nan_sign == m_min.sign && nan_sign == m_max.sign))
1363 {
1364 signbit = nan_sign;
1365 return true;
1366 }
1367 return false;
67263231
AH
1368}
1369
658788f3
AH
1370// If range has a NAN with a known sign, set it in SIGNBIT and return
1371// TRUE.
1372
1373inline bool
1374frange::nan_signbit_p (bool &signbit) const
1375{
1376 if (undefined_p ())
1377 return false;
1378
1379 if (m_pos_nan == m_neg_nan)
1380 return false;
1381
1382 signbit = m_neg_nan;
1383 return true;
1384}
1385
cca78449 1386#endif // GCC_VALUE_RANGE_H