]> gcc.gnu.org Git - gcc.git/blame - gcc/value-range-storage.cc
Daily bump.
[gcc.git] / gcc / value-range-storage.cc
CommitLineData
a26f3eb2 1/* Support routines for vrange storage.
aeee4812 2 Copyright (C) 2022-2023 Free Software Foundation, Inc.
a26f3eb2
AH
3 Contributed by Aldy Hernandez <aldyh@redhat.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "backend.h"
25#include "tree.h"
26#include "gimple.h"
27#include "ssa.h"
28#include "tree-pretty-print.h"
29#include "fold-const.h"
30#include "gimple-range.h"
31#include "value-range-storage.h"
32
0a7e721a
AH
33// Return a newly allocated slot holding R, or NULL if storing a range
34// of R's type is not supported.
a26f3eb2
AH
35
36void *
37vrange_storage::alloc_slot (const vrange &r)
38{
39 gcc_checking_assert (m_alloc);
40
41 if (is_a <irange> (r))
42 return irange_storage_slot::alloc_slot (*m_alloc, as_a <irange> (r));
5f7e187e
AH
43 if (is_a <frange> (r))
44 return frange_storage_slot::alloc_slot (*m_alloc, as_a <frange> (r));
a26f3eb2
AH
45 return NULL;
46}
47
48// Set SLOT to R.
49
50void
51vrange_storage::set_vrange (void *slot, const vrange &r)
52{
53 if (is_a <irange> (r))
54 {
55 irange_storage_slot *s = static_cast <irange_storage_slot *> (slot);
56 gcc_checking_assert (s->fits_p (as_a <irange> (r)));
57 s->set_irange (as_a <irange> (r));
58 }
5f7e187e
AH
59 else if (is_a <frange> (r))
60 {
61 frange_storage_slot *s = static_cast <frange_storage_slot *> (slot);
62 gcc_checking_assert (s->fits_p (as_a <frange> (r)));
63 s->set_frange (as_a <frange> (r));
64 }
a26f3eb2
AH
65 else
66 gcc_unreachable ();
67}
68
69// Restore R from SLOT. TYPE is the type of R.
70
71void
72vrange_storage::get_vrange (const void *slot, vrange &r, tree type)
73{
74 if (is_a <irange> (r))
75 {
76 const irange_storage_slot *s
77 = static_cast <const irange_storage_slot *> (slot);
78 s->get_irange (as_a <irange> (r), type);
79 }
5f7e187e
AH
80 else if (is_a <frange> (r))
81 {
82 const frange_storage_slot *s
83 = static_cast <const frange_storage_slot *> (slot);
84 s->get_frange (as_a <frange> (r), type);
85 }
a26f3eb2
AH
86 else
87 gcc_unreachable ();
88}
89
90// Return TRUE if SLOT can fit R.
91
92bool
93vrange_storage::fits_p (const void *slot, const vrange &r)
94{
95 if (is_a <irange> (r))
96 {
97 const irange_storage_slot *s
98 = static_cast <const irange_storage_slot *> (slot);
99 return s->fits_p (as_a <irange> (r));
100 }
5f7e187e
AH
101 if (is_a <frange> (r))
102 {
103 const frange_storage_slot *s
104 = static_cast <const frange_storage_slot *> (slot);
105 return s->fits_p (as_a <frange> (r));
106 }
a26f3eb2
AH
107 gcc_unreachable ();
108 return false;
109}
110
111// Factory that creates a new irange_storage_slot object containing R.
112// This is the only way to construct an irange slot as stack creation
113// is disallowed.
114
115irange_storage_slot *
116irange_storage_slot::alloc_slot (vrange_allocator &allocator, const irange &r)
117{
118 size_t size = irange_storage_slot::size (r);
119 irange_storage_slot *p
120 = static_cast <irange_storage_slot *> (allocator.alloc (size));
121 new (p) irange_storage_slot (r);
122 return p;
123}
124
125// Initialize the current slot with R.
126
127irange_storage_slot::irange_storage_slot (const irange &r)
128{
129 gcc_checking_assert (!r.undefined_p ());
130
131 unsigned prec = TYPE_PRECISION (r.type ());
132 unsigned n = num_wide_ints_needed (r);
133 if (n > MAX_INTS)
134 {
135 int_range<MAX_PAIRS> squash (r);
136 m_ints.set_precision (prec, num_wide_ints_needed (squash));
137 set_irange (squash);
138 }
139 else
140 {
141 m_ints.set_precision (prec, n);
142 set_irange (r);
143 }
144}
145
146// Store R into the current slot.
147
148void
149irange_storage_slot::set_irange (const irange &r)
150{
151 gcc_checking_assert (fits_p (r));
152
7df3693f 153 m_ints[0] = r.get_nonzero_bits ();
4e82205b 154
a26f3eb2
AH
155 unsigned pairs = r.num_pairs ();
156 for (unsigned i = 0; i < pairs; ++i)
157 {
158 m_ints[i*2 + 1] = r.lower_bound (i);
159 m_ints[i*2 + 2] = r.upper_bound (i);
160 }
161}
162
163// Restore a range of TYPE from the current slot into R.
164
165void
166irange_storage_slot::get_irange (irange &r, tree type) const
167{
168 gcc_checking_assert (TYPE_PRECISION (type) == m_ints.get_precision ());
169
170 r.set_undefined ();
171 unsigned nelements = m_ints.num_elements ();
172 for (unsigned i = 1; i < nelements; i += 2)
173 {
174 int_range<2> tmp (type, m_ints[i], m_ints[i + 1]);
175 r.union_ (tmp);
176 }
4e82205b 177 r.set_nonzero_bits (get_nonzero_bits ());
a26f3eb2
AH
178}
179
180// Return the size in bytes to allocate a slot that can hold R.
181
182size_t
183irange_storage_slot::size (const irange &r)
184{
185 gcc_checking_assert (!r.undefined_p ());
186
187 unsigned prec = TYPE_PRECISION (r.type ());
188 unsigned n = num_wide_ints_needed (r);
189 if (n > MAX_INTS)
190 n = MAX_INTS;
191 return (sizeof (irange_storage_slot)
192 + trailing_wide_ints<MAX_INTS>::extra_size (prec, n));
193}
194
195// Return the number of wide ints needed to represent R.
196
197unsigned int
198irange_storage_slot::num_wide_ints_needed (const irange &r)
199{
200 return r.num_pairs () * 2 + 1;
201}
202
203// Return TRUE if R fits in the current slot.
204
205bool
206irange_storage_slot::fits_p (const irange &r) const
207{
208 return m_ints.num_elements () >= num_wide_ints_needed (r);
209}
210
211// Dump the current slot.
212
213void
214irange_storage_slot::dump () const
215{
216 fprintf (stderr, "raw irange_storage_slot:\n");
217 for (unsigned i = 1; i < m_ints.num_elements (); i += 2)
218 {
219 m_ints[i].dump ();
220 m_ints[i + 1].dump ();
221 }
222 fprintf (stderr, "NONZERO ");
223 wide_int nz = get_nonzero_bits ();
224 nz.dump ();
225}
226
227DEBUG_FUNCTION void
228debug (const irange_storage_slot &storage)
229{
230 storage.dump ();
231 fprintf (stderr, "\n");
232}
5f7e187e
AH
233
234// Implementation of frange_storage_slot.
235
236frange_storage_slot *
237frange_storage_slot::alloc_slot (vrange_allocator &allocator, const frange &r)
238{
239 size_t size = sizeof (frange_storage_slot);
240 frange_storage_slot *p
241 = static_cast <frange_storage_slot *> (allocator.alloc (size));
242 new (p) frange_storage_slot (r);
243 return p;
244}
245
246void
247frange_storage_slot::set_frange (const frange &r)
248{
249 gcc_checking_assert (fits_p (r));
250 gcc_checking_assert (!r.undefined_p ());
251
91746147 252 m_kind = r.m_kind;
25dd2768
AH
253 m_min = r.m_min;
254 m_max = r.m_max;
91746147
AH
255 m_pos_nan = r.m_pos_nan;
256 m_neg_nan = r.m_neg_nan;
5f7e187e
AH
257}
258
259void
260frange_storage_slot::get_frange (frange &r, tree type) const
261{
262 gcc_checking_assert (r.supports_type_p (type));
263
2b1fb720
AH
264 // Handle explicit NANs.
265 if (m_kind == VR_NAN)
266 {
267 if (HONOR_NANS (type))
268 {
269 if (m_pos_nan && m_neg_nan)
270 r.set_nan (type);
271 else
272 r.set_nan (type, m_neg_nan);
273 }
274 else
275 r.set_undefined ();
276 return;
277 }
278
4eadbe80
AH
279 // We use the constructor to create the new range instead of writing
280 // out the bits into the frange directly, because the global range
281 // being read may be being inlined into a function with different
282 // restrictions as when it was originally written. We want to make
283 // sure the resulting range is canonicalized correctly for the new
284 // consumer.
2b1fb720
AH
285 r = frange (type, m_min, m_max, m_kind);
286
287 // The constructor will set the NAN bits for HONOR_NANS, but we must
288 // make sure to set the NAN sign if known.
289 if (HONOR_NANS (type) && (m_pos_nan ^ m_neg_nan) == 1)
290 r.update_nan (m_neg_nan);
4eadbe80
AH
291 else if (!m_pos_nan && !m_neg_nan)
292 r.clear_nan ();
5f7e187e
AH
293}
294
295bool
296frange_storage_slot::fits_p (const frange &) const
297{
298 return true;
299}
This page took 0.676153 seconds and 5 git commands to generate.