11debfc3dSmrg /* Functions to support general ended bitmaps.
2*8feb0f0bSmrg Copyright (C) 1997-2020 Free Software Foundation, Inc.
31debfc3dSmrg
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
71debfc3dSmrg the terms of the GNU General Public License as published by the Free
81debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
91debfc3dSmrg version.
101debfc3dSmrg
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
121debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3. If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>. */
191debfc3dSmrg
201debfc3dSmrg #include "config.h"
211debfc3dSmrg #include "system.h"
221debfc3dSmrg #include "coretypes.h"
231debfc3dSmrg #include "bitmap.h"
241debfc3dSmrg #include "selftest.h"
251debfc3dSmrg
261debfc3dSmrg /* Memory allocation statistics purpose instance. */
271debfc3dSmrg mem_alloc_description<bitmap_usage> bitmap_mem_desc;
281debfc3dSmrg
29c0a68be4Smrg /* Static zero-initialized bitmap obstack used for default initialization
30c0a68be4Smrg of bitmap_head. */
31c0a68be4Smrg bitmap_obstack bitmap_head::crashme;
32c0a68be4Smrg
33c0a68be4Smrg static bitmap_element *bitmap_tree_listify_from (bitmap, bitmap_element *);
34c0a68be4Smrg
351debfc3dSmrg /* Register new bitmap. */
361debfc3dSmrg void
bitmap_register(bitmap b MEM_STAT_DECL)371debfc3dSmrg bitmap_register (bitmap b MEM_STAT_DECL)
381debfc3dSmrg {
39*8feb0f0bSmrg static unsigned alloc_descriptor_max_uid = 1;
40*8feb0f0bSmrg gcc_assert (b->alloc_descriptor == 0);
41*8feb0f0bSmrg b->alloc_descriptor = alloc_descriptor_max_uid++;
42*8feb0f0bSmrg
43*8feb0f0bSmrg bitmap_mem_desc.register_descriptor (b->get_descriptor (), BITMAP_ORIGIN,
44*8feb0f0bSmrg false FINAL_PASS_MEM_STAT);
451debfc3dSmrg }
461debfc3dSmrg
471debfc3dSmrg /* Account the overhead. */
481debfc3dSmrg static void
register_overhead(bitmap b,size_t amount)491debfc3dSmrg register_overhead (bitmap b, size_t amount)
501debfc3dSmrg {
51*8feb0f0bSmrg unsigned *d = b->get_descriptor ();
52*8feb0f0bSmrg if (bitmap_mem_desc.contains_descriptor_for_instance (d))
53*8feb0f0bSmrg bitmap_mem_desc.register_instance_overhead (amount, d);
541debfc3dSmrg }
551debfc3dSmrg
56*8feb0f0bSmrg /* Release the overhead. */
57*8feb0f0bSmrg static void
release_overhead(bitmap b,size_t amount,bool remove_from_map)58*8feb0f0bSmrg release_overhead (bitmap b, size_t amount, bool remove_from_map)
59*8feb0f0bSmrg {
60*8feb0f0bSmrg unsigned *d = b->get_descriptor ();
61*8feb0f0bSmrg if (bitmap_mem_desc.contains_descriptor_for_instance (d))
62*8feb0f0bSmrg bitmap_mem_desc.release_instance_overhead (d, amount, remove_from_map);
63*8feb0f0bSmrg }
64*8feb0f0bSmrg
65*8feb0f0bSmrg
661debfc3dSmrg /* Global data */
671debfc3dSmrg bitmap_element bitmap_zero_bits; /* An element of all zero bits. */
681debfc3dSmrg bitmap_obstack bitmap_default_obstack; /* The default bitmap obstack. */
691debfc3dSmrg static int bitmap_default_obstack_depth;
701debfc3dSmrg static GTY((deletable)) bitmap_element *bitmap_ggc_free; /* Freelist of
711debfc3dSmrg GC'd elements. */
721debfc3dSmrg
731debfc3dSmrg
74c0a68be4Smrg /* Bitmap memory management. */
751debfc3dSmrg
76c0a68be4Smrg /* Add ELT to the appropriate freelist. */
771debfc3dSmrg static inline void
bitmap_elem_to_freelist(bitmap head,bitmap_element * elt)781debfc3dSmrg bitmap_elem_to_freelist (bitmap head, bitmap_element *elt)
791debfc3dSmrg {
801debfc3dSmrg bitmap_obstack *bit_obstack = head->obstack;
811debfc3dSmrg
82c0a68be4Smrg if (GATHER_STATISTICS)
83*8feb0f0bSmrg release_overhead (head, sizeof (bitmap_element), false);
84c0a68be4Smrg
851debfc3dSmrg elt->next = NULL;
861debfc3dSmrg elt->indx = -1;
871debfc3dSmrg if (bit_obstack)
881debfc3dSmrg {
891debfc3dSmrg elt->prev = bit_obstack->elements;
901debfc3dSmrg bit_obstack->elements = elt;
911debfc3dSmrg }
921debfc3dSmrg else
931debfc3dSmrg {
941debfc3dSmrg elt->prev = bitmap_ggc_free;
951debfc3dSmrg bitmap_ggc_free = elt;
961debfc3dSmrg }
971debfc3dSmrg }
981debfc3dSmrg
991debfc3dSmrg /* Allocate a bitmap element. The bits are cleared, but nothing else is. */
1001debfc3dSmrg
1011debfc3dSmrg static inline bitmap_element *
bitmap_element_allocate(bitmap head)1021debfc3dSmrg bitmap_element_allocate (bitmap head)
1031debfc3dSmrg {
1041debfc3dSmrg bitmap_element *element;
1051debfc3dSmrg bitmap_obstack *bit_obstack = head->obstack;
1061debfc3dSmrg
1071debfc3dSmrg if (bit_obstack)
1081debfc3dSmrg {
1091debfc3dSmrg element = bit_obstack->elements;
1101debfc3dSmrg
1111debfc3dSmrg if (element)
1121debfc3dSmrg /* Use up the inner list first before looking at the next
1131debfc3dSmrg element of the outer list. */
1141debfc3dSmrg if (element->next)
1151debfc3dSmrg {
1161debfc3dSmrg bit_obstack->elements = element->next;
1171debfc3dSmrg bit_obstack->elements->prev = element->prev;
1181debfc3dSmrg }
1191debfc3dSmrg else
1201debfc3dSmrg /* Inner list was just a singleton. */
1211debfc3dSmrg bit_obstack->elements = element->prev;
1221debfc3dSmrg else
1231debfc3dSmrg element = XOBNEW (&bit_obstack->obstack, bitmap_element);
1241debfc3dSmrg }
1251debfc3dSmrg else
1261debfc3dSmrg {
1271debfc3dSmrg element = bitmap_ggc_free;
1281debfc3dSmrg if (element)
1291debfc3dSmrg /* Use up the inner list first before looking at the next
1301debfc3dSmrg element of the outer list. */
1311debfc3dSmrg if (element->next)
1321debfc3dSmrg {
1331debfc3dSmrg bitmap_ggc_free = element->next;
1341debfc3dSmrg bitmap_ggc_free->prev = element->prev;
1351debfc3dSmrg }
1361debfc3dSmrg else
1371debfc3dSmrg /* Inner list was just a singleton. */
1381debfc3dSmrg bitmap_ggc_free = element->prev;
1391debfc3dSmrg else
1401debfc3dSmrg element = ggc_alloc<bitmap_element> ();
1411debfc3dSmrg }
1421debfc3dSmrg
1431debfc3dSmrg if (GATHER_STATISTICS)
1441debfc3dSmrg register_overhead (head, sizeof (bitmap_element));
1451debfc3dSmrg
1461debfc3dSmrg memset (element->bits, 0, sizeof (element->bits));
1471debfc3dSmrg
1481debfc3dSmrg return element;
1491debfc3dSmrg }
1501debfc3dSmrg
151c0a68be4Smrg /* Remove ELT and all following elements from bitmap HEAD.
152c0a68be4Smrg Put the released elements in the freelist for HEAD. */
1531debfc3dSmrg
1541debfc3dSmrg void
bitmap_elt_clear_from(bitmap head,bitmap_element * elt)1551debfc3dSmrg bitmap_elt_clear_from (bitmap head, bitmap_element *elt)
1561debfc3dSmrg {
1571debfc3dSmrg bitmap_element *prev;
1581debfc3dSmrg bitmap_obstack *bit_obstack = head->obstack;
1591debfc3dSmrg
160c0a68be4Smrg if (!elt)
161c0a68be4Smrg return;
162c0a68be4Smrg
163c0a68be4Smrg if (head->tree_form)
164c0a68be4Smrg elt = bitmap_tree_listify_from (head, elt);
1651debfc3dSmrg
1661debfc3dSmrg if (GATHER_STATISTICS)
1671debfc3dSmrg {
1681debfc3dSmrg int n = 0;
1691debfc3dSmrg for (prev = elt; prev; prev = prev->next)
1701debfc3dSmrg n++;
171*8feb0f0bSmrg release_overhead (head, sizeof (bitmap_element) * n, false);
1721debfc3dSmrg }
1731debfc3dSmrg
1741debfc3dSmrg prev = elt->prev;
1751debfc3dSmrg if (prev)
1761debfc3dSmrg {
1771debfc3dSmrg prev->next = NULL;
1781debfc3dSmrg if (head->current->indx > prev->indx)
1791debfc3dSmrg {
1801debfc3dSmrg head->current = prev;
1811debfc3dSmrg head->indx = prev->indx;
1821debfc3dSmrg }
1831debfc3dSmrg }
1841debfc3dSmrg else
1851debfc3dSmrg {
1861debfc3dSmrg head->first = NULL;
1871debfc3dSmrg head->current = NULL;
1881debfc3dSmrg head->indx = 0;
1891debfc3dSmrg }
1901debfc3dSmrg
1911debfc3dSmrg /* Put the entire list onto the freelist in one operation. */
1921debfc3dSmrg if (bit_obstack)
1931debfc3dSmrg {
1941debfc3dSmrg elt->prev = bit_obstack->elements;
1951debfc3dSmrg bit_obstack->elements = elt;
1961debfc3dSmrg }
1971debfc3dSmrg else
1981debfc3dSmrg {
1991debfc3dSmrg elt->prev = bitmap_ggc_free;
2001debfc3dSmrg bitmap_ggc_free = elt;
2011debfc3dSmrg }
2021debfc3dSmrg }
203c0a68be4Smrg
204c0a68be4Smrg /* Linked-list view of bitmaps.
2051debfc3dSmrg
206c0a68be4Smrg In this representation, the bitmap elements form a double-linked list
207c0a68be4Smrg with elements sorted by increasing index. */
208c0a68be4Smrg
209c0a68be4Smrg /* Link the bitmap element into the current bitmap linked list. */
210c0a68be4Smrg
211c0a68be4Smrg static inline void
bitmap_list_link_element(bitmap head,bitmap_element * element)212c0a68be4Smrg bitmap_list_link_element (bitmap head, bitmap_element *element)
213c0a68be4Smrg {
214c0a68be4Smrg unsigned int indx = element->indx;
215c0a68be4Smrg bitmap_element *ptr;
216c0a68be4Smrg
217c0a68be4Smrg gcc_checking_assert (!head->tree_form);
218c0a68be4Smrg
219c0a68be4Smrg /* If this is the first and only element, set it in. */
220c0a68be4Smrg if (head->first == 0)
221c0a68be4Smrg {
222c0a68be4Smrg element->next = element->prev = 0;
223c0a68be4Smrg head->first = element;
224c0a68be4Smrg }
225c0a68be4Smrg
226c0a68be4Smrg /* If this index is less than that of the current element, it goes someplace
227c0a68be4Smrg before the current element. */
228c0a68be4Smrg else if (indx < head->indx)
229c0a68be4Smrg {
230c0a68be4Smrg for (ptr = head->current;
231c0a68be4Smrg ptr->prev != 0 && ptr->prev->indx > indx;
232c0a68be4Smrg ptr = ptr->prev)
233c0a68be4Smrg ;
234c0a68be4Smrg
235c0a68be4Smrg if (ptr->prev)
236c0a68be4Smrg ptr->prev->next = element;
237c0a68be4Smrg else
238c0a68be4Smrg head->first = element;
239c0a68be4Smrg
240c0a68be4Smrg element->prev = ptr->prev;
241c0a68be4Smrg element->next = ptr;
242c0a68be4Smrg ptr->prev = element;
243c0a68be4Smrg }
244c0a68be4Smrg
245c0a68be4Smrg /* Otherwise, it must go someplace after the current element. */
246c0a68be4Smrg else
247c0a68be4Smrg {
248c0a68be4Smrg for (ptr = head->current;
249c0a68be4Smrg ptr->next != 0 && ptr->next->indx < indx;
250c0a68be4Smrg ptr = ptr->next)
251c0a68be4Smrg ;
252c0a68be4Smrg
253c0a68be4Smrg if (ptr->next)
254c0a68be4Smrg ptr->next->prev = element;
255c0a68be4Smrg
256c0a68be4Smrg element->next = ptr->next;
257c0a68be4Smrg element->prev = ptr;
258c0a68be4Smrg ptr->next = element;
259c0a68be4Smrg }
260c0a68be4Smrg
261c0a68be4Smrg /* Set up so this is the first element searched. */
262c0a68be4Smrg head->current = element;
263c0a68be4Smrg head->indx = indx;
264c0a68be4Smrg }
265c0a68be4Smrg
266c0a68be4Smrg /* Unlink the bitmap element from the current bitmap linked list,
267c0a68be4Smrg and return it to the freelist. */
268c0a68be4Smrg
269c0a68be4Smrg static inline void
270*8feb0f0bSmrg bitmap_list_unlink_element (bitmap head, bitmap_element *element,
271*8feb0f0bSmrg bool to_freelist = true)
272c0a68be4Smrg {
273c0a68be4Smrg bitmap_element *next = element->next;
274c0a68be4Smrg bitmap_element *prev = element->prev;
275c0a68be4Smrg
276c0a68be4Smrg gcc_checking_assert (!head->tree_form);
277c0a68be4Smrg
278c0a68be4Smrg if (prev)
279c0a68be4Smrg prev->next = next;
280c0a68be4Smrg
281c0a68be4Smrg if (next)
282c0a68be4Smrg next->prev = prev;
283c0a68be4Smrg
284c0a68be4Smrg if (head->first == element)
285c0a68be4Smrg head->first = next;
286c0a68be4Smrg
287c0a68be4Smrg /* Since the first thing we try is to insert before current,
288c0a68be4Smrg make current the next entry in preference to the previous. */
289c0a68be4Smrg if (head->current == element)
290c0a68be4Smrg {
291c0a68be4Smrg head->current = next != 0 ? next : prev;
292c0a68be4Smrg if (head->current)
293c0a68be4Smrg head->indx = head->current->indx;
294c0a68be4Smrg else
295c0a68be4Smrg head->indx = 0;
296c0a68be4Smrg }
297c0a68be4Smrg
298*8feb0f0bSmrg if (to_freelist)
299c0a68be4Smrg bitmap_elem_to_freelist (head, element);
300c0a68be4Smrg }
301c0a68be4Smrg
302*8feb0f0bSmrg /* Insert a new uninitialized element (or NODE if not NULL) into bitmap
303*8feb0f0bSmrg HEAD after element ELT. If ELT is NULL, insert the element at the start.
304*8feb0f0bSmrg Return the new element. */
305c0a68be4Smrg
306c0a68be4Smrg static bitmap_element *
307c0a68be4Smrg bitmap_list_insert_element_after (bitmap head,
308*8feb0f0bSmrg bitmap_element *elt, unsigned int indx,
309*8feb0f0bSmrg bitmap_element *node = NULL)
310c0a68be4Smrg {
311*8feb0f0bSmrg if (!node)
312*8feb0f0bSmrg node = bitmap_element_allocate (head);
313c0a68be4Smrg node->indx = indx;
314c0a68be4Smrg
315c0a68be4Smrg gcc_checking_assert (!head->tree_form);
316c0a68be4Smrg
317c0a68be4Smrg if (!elt)
318c0a68be4Smrg {
319c0a68be4Smrg if (!head->current)
320c0a68be4Smrg {
321c0a68be4Smrg head->current = node;
322c0a68be4Smrg head->indx = indx;
323c0a68be4Smrg }
324c0a68be4Smrg node->next = head->first;
325c0a68be4Smrg if (node->next)
326c0a68be4Smrg node->next->prev = node;
327c0a68be4Smrg head->first = node;
328c0a68be4Smrg node->prev = NULL;
329c0a68be4Smrg }
330c0a68be4Smrg else
331c0a68be4Smrg {
332c0a68be4Smrg gcc_checking_assert (head->current);
333c0a68be4Smrg node->next = elt->next;
334c0a68be4Smrg if (node->next)
335c0a68be4Smrg node->next->prev = node;
336c0a68be4Smrg elt->next = node;
337c0a68be4Smrg node->prev = elt;
338c0a68be4Smrg }
339c0a68be4Smrg return node;
340c0a68be4Smrg }
341c0a68be4Smrg
342c0a68be4Smrg /* Return the element for INDX, or NULL if the element doesn't exist.
343c0a68be4Smrg Update the `current' field even if we can't find an element that
344c0a68be4Smrg would hold the bitmap's bit to make eventual allocation
345c0a68be4Smrg faster. */
346c0a68be4Smrg
347c0a68be4Smrg static inline bitmap_element *
bitmap_list_find_element(bitmap head,unsigned int indx)348c0a68be4Smrg bitmap_list_find_element (bitmap head, unsigned int indx)
349c0a68be4Smrg {
350c0a68be4Smrg bitmap_element *element;
351c0a68be4Smrg
352c0a68be4Smrg if (head->current == NULL
353c0a68be4Smrg || head->indx == indx)
354c0a68be4Smrg return head->current;
355c0a68be4Smrg
356c0a68be4Smrg if (head->current == head->first
357c0a68be4Smrg && head->first->next == NULL)
358c0a68be4Smrg return NULL;
359c0a68be4Smrg
360c0a68be4Smrg /* Usage can be NULL due to allocated bitmaps for which we do not
361c0a68be4Smrg call initialize function. */
362c0a68be4Smrg bitmap_usage *usage = NULL;
363c0a68be4Smrg if (GATHER_STATISTICS)
364c0a68be4Smrg usage = bitmap_mem_desc.get_descriptor_for_instance (head);
365c0a68be4Smrg
366c0a68be4Smrg /* This bitmap has more than one element, and we're going to look
367c0a68be4Smrg through the elements list. Count that as a search. */
368c0a68be4Smrg if (GATHER_STATISTICS && usage)
369c0a68be4Smrg usage->m_nsearches++;
370c0a68be4Smrg
371c0a68be4Smrg if (head->indx < indx)
372c0a68be4Smrg /* INDX is beyond head->indx. Search from head->current
373c0a68be4Smrg forward. */
374c0a68be4Smrg for (element = head->current;
375c0a68be4Smrg element->next != 0 && element->indx < indx;
376c0a68be4Smrg element = element->next)
377c0a68be4Smrg {
378c0a68be4Smrg if (GATHER_STATISTICS && usage)
379c0a68be4Smrg usage->m_search_iter++;
380c0a68be4Smrg }
381c0a68be4Smrg
382c0a68be4Smrg else if (head->indx / 2 < indx)
383c0a68be4Smrg /* INDX is less than head->indx and closer to head->indx than to
384c0a68be4Smrg 0. Search from head->current backward. */
385c0a68be4Smrg for (element = head->current;
386c0a68be4Smrg element->prev != 0 && element->indx > indx;
387c0a68be4Smrg element = element->prev)
388c0a68be4Smrg {
389c0a68be4Smrg if (GATHER_STATISTICS && usage)
390c0a68be4Smrg usage->m_search_iter++;
391c0a68be4Smrg }
392c0a68be4Smrg
393c0a68be4Smrg else
394c0a68be4Smrg /* INDX is less than head->indx and closer to 0 than to
395c0a68be4Smrg head->indx. Search from head->first forward. */
396c0a68be4Smrg for (element = head->first;
397c0a68be4Smrg element->next != 0 && element->indx < indx;
398c0a68be4Smrg element = element->next)
399c0a68be4Smrg {
400c0a68be4Smrg if (GATHER_STATISTICS && usage)
401c0a68be4Smrg usage->m_search_iter++;
402c0a68be4Smrg }
403c0a68be4Smrg
404c0a68be4Smrg /* `element' is the nearest to the one we want. If it's not the one we
405c0a68be4Smrg want, the one we want doesn't exist. */
406c0a68be4Smrg gcc_checking_assert (element != NULL);
407c0a68be4Smrg head->current = element;
408c0a68be4Smrg head->indx = element->indx;
409c0a68be4Smrg if (element->indx != indx)
410c0a68be4Smrg element = 0;
411c0a68be4Smrg return element;
412c0a68be4Smrg }
413c0a68be4Smrg
414c0a68be4Smrg
415c0a68be4Smrg /* Splay-tree view of bitmaps.
416c0a68be4Smrg
417c0a68be4Smrg This is an almost one-to-one the implementatin of the simple top-down
418c0a68be4Smrg splay tree in Sleator and Tarjan's "Self-adjusting Binary Search Trees".
419c0a68be4Smrg It is probably not the most efficient form of splay trees, but it should
420c0a68be4Smrg be good enough to experiment with this idea of bitmaps-as-trees.
421c0a68be4Smrg
422c0a68be4Smrg For all functions below, the variable or function argument "t" is a node
423c0a68be4Smrg in the tree, and "e" is a temporary or new node in the tree. The rest
424c0a68be4Smrg is sufficiently straigh-forward (and very well explained in the paper)
425c0a68be4Smrg that comment would only clutter things. */
426c0a68be4Smrg
427c0a68be4Smrg static inline void
bitmap_tree_link_left(bitmap_element * & t,bitmap_element * & l)428c0a68be4Smrg bitmap_tree_link_left (bitmap_element * &t, bitmap_element * &l)
429c0a68be4Smrg {
430c0a68be4Smrg l->next = t;
431c0a68be4Smrg l = t;
432c0a68be4Smrg t = t->next;
433c0a68be4Smrg }
434c0a68be4Smrg
435c0a68be4Smrg static inline void
bitmap_tree_link_right(bitmap_element * & t,bitmap_element * & r)436c0a68be4Smrg bitmap_tree_link_right (bitmap_element * &t, bitmap_element * &r)
437c0a68be4Smrg {
438c0a68be4Smrg r->prev = t;
439c0a68be4Smrg r = t;
440c0a68be4Smrg t = t->prev;
441c0a68be4Smrg }
442c0a68be4Smrg
443c0a68be4Smrg static inline void
bitmap_tree_rotate_left(bitmap_element * & t)444c0a68be4Smrg bitmap_tree_rotate_left (bitmap_element * &t)
445c0a68be4Smrg {
446c0a68be4Smrg bitmap_element *e = t->next;
447c0a68be4Smrg t->next = t->next->prev;
448c0a68be4Smrg e->prev = t;
449c0a68be4Smrg t = e;
450c0a68be4Smrg }
451c0a68be4Smrg
452c0a68be4Smrg static inline void
bitmap_tree_rotate_right(bitmap_element * & t)453c0a68be4Smrg bitmap_tree_rotate_right (bitmap_element * &t)
454c0a68be4Smrg {
455c0a68be4Smrg bitmap_element *e = t->prev;
456c0a68be4Smrg t->prev = t->prev->next;
457c0a68be4Smrg e->next = t;
458c0a68be4Smrg t = e;
459c0a68be4Smrg }
460c0a68be4Smrg
461c0a68be4Smrg static bitmap_element *
bitmap_tree_splay(bitmap head,bitmap_element * t,unsigned int indx)462c0a68be4Smrg bitmap_tree_splay (bitmap head, bitmap_element *t, unsigned int indx)
463c0a68be4Smrg {
464c0a68be4Smrg bitmap_element N, *l, *r;
465c0a68be4Smrg
466c0a68be4Smrg if (t == NULL)
467c0a68be4Smrg return NULL;
468c0a68be4Smrg
469c0a68be4Smrg bitmap_usage *usage = NULL;
470c0a68be4Smrg if (GATHER_STATISTICS)
471c0a68be4Smrg usage = bitmap_mem_desc.get_descriptor_for_instance (head);
472c0a68be4Smrg
473c0a68be4Smrg N.prev = N.next = NULL;
474c0a68be4Smrg l = r = &N;
475c0a68be4Smrg
476c0a68be4Smrg while (indx != t->indx)
477c0a68be4Smrg {
478c0a68be4Smrg if (GATHER_STATISTICS && usage)
479c0a68be4Smrg usage->m_search_iter++;
480c0a68be4Smrg
481c0a68be4Smrg if (indx < t->indx)
482c0a68be4Smrg {
483c0a68be4Smrg if (t->prev != NULL && indx < t->prev->indx)
484c0a68be4Smrg bitmap_tree_rotate_right (t);
485c0a68be4Smrg if (t->prev == NULL)
486c0a68be4Smrg break;
487c0a68be4Smrg bitmap_tree_link_right (t, r);
488c0a68be4Smrg }
489c0a68be4Smrg else if (indx > t->indx)
490c0a68be4Smrg {
491c0a68be4Smrg if (t->next != NULL && indx > t->next->indx)
492c0a68be4Smrg bitmap_tree_rotate_left (t);
493c0a68be4Smrg if (t->next == NULL)
494c0a68be4Smrg break;
495c0a68be4Smrg bitmap_tree_link_left (t, l);
496c0a68be4Smrg }
497c0a68be4Smrg }
498c0a68be4Smrg
499c0a68be4Smrg l->next = t->prev;
500c0a68be4Smrg r->prev = t->next;
501c0a68be4Smrg t->prev = N.next;
502c0a68be4Smrg t->next = N.prev;
503c0a68be4Smrg return t;
504c0a68be4Smrg }
505c0a68be4Smrg
506c0a68be4Smrg /* Link bitmap element E into the current bitmap splay tree. */
507c0a68be4Smrg
508c0a68be4Smrg static inline void
bitmap_tree_link_element(bitmap head,bitmap_element * e)509c0a68be4Smrg bitmap_tree_link_element (bitmap head, bitmap_element *e)
510c0a68be4Smrg {
511c0a68be4Smrg if (head->first == NULL)
512c0a68be4Smrg e->prev = e->next = NULL;
513c0a68be4Smrg else
514c0a68be4Smrg {
515c0a68be4Smrg bitmap_element *t = bitmap_tree_splay (head, head->first, e->indx);
516c0a68be4Smrg if (e->indx < t->indx)
517c0a68be4Smrg {
518c0a68be4Smrg e->prev = t->prev;
519c0a68be4Smrg e->next = t;
520c0a68be4Smrg t->prev = NULL;
521c0a68be4Smrg }
522c0a68be4Smrg else if (e->indx > t->indx)
523c0a68be4Smrg {
524c0a68be4Smrg e->next = t->next;
525c0a68be4Smrg e->prev = t;
526c0a68be4Smrg t->next = NULL;
527c0a68be4Smrg }
528c0a68be4Smrg else
529c0a68be4Smrg gcc_unreachable ();
530c0a68be4Smrg }
531c0a68be4Smrg head->first = e;
532c0a68be4Smrg head->current = e;
533c0a68be4Smrg head->indx = e->indx;
534c0a68be4Smrg }
535c0a68be4Smrg
536c0a68be4Smrg /* Unlink bitmap element E from the current bitmap splay tree,
537c0a68be4Smrg and return it to the freelist. */
538c0a68be4Smrg
539c0a68be4Smrg static void
bitmap_tree_unlink_element(bitmap head,bitmap_element * e)540c0a68be4Smrg bitmap_tree_unlink_element (bitmap head, bitmap_element *e)
541c0a68be4Smrg {
542c0a68be4Smrg bitmap_element *t = bitmap_tree_splay (head, head->first, e->indx);
543c0a68be4Smrg
544c0a68be4Smrg gcc_checking_assert (t == e);
545c0a68be4Smrg
546c0a68be4Smrg if (e->prev == NULL)
547c0a68be4Smrg t = e->next;
548c0a68be4Smrg else
549c0a68be4Smrg {
550c0a68be4Smrg t = bitmap_tree_splay (head, e->prev, e->indx);
551c0a68be4Smrg t->next = e->next;
552c0a68be4Smrg }
553c0a68be4Smrg head->first = t;
554c0a68be4Smrg head->current = t;
555c0a68be4Smrg head->indx = (t != NULL) ? t->indx : 0;
556c0a68be4Smrg
557c0a68be4Smrg bitmap_elem_to_freelist (head, e);
558c0a68be4Smrg }
559c0a68be4Smrg
560c0a68be4Smrg /* Return the element for INDX, or NULL if the element doesn't exist. */
561c0a68be4Smrg
562c0a68be4Smrg static inline bitmap_element *
bitmap_tree_find_element(bitmap head,unsigned int indx)563c0a68be4Smrg bitmap_tree_find_element (bitmap head, unsigned int indx)
564c0a68be4Smrg {
565c0a68be4Smrg if (head->current == NULL
566c0a68be4Smrg || head->indx == indx)
567c0a68be4Smrg return head->current;
568c0a68be4Smrg
569c0a68be4Smrg /* Usage can be NULL due to allocated bitmaps for which we do not
570c0a68be4Smrg call initialize function. */
571c0a68be4Smrg bitmap_usage *usage = NULL;
572c0a68be4Smrg if (GATHER_STATISTICS)
573c0a68be4Smrg usage = bitmap_mem_desc.get_descriptor_for_instance (head);
574c0a68be4Smrg
575c0a68be4Smrg /* This bitmap has more than one element, and we're going to look
576c0a68be4Smrg through the elements list. Count that as a search. */
577c0a68be4Smrg if (GATHER_STATISTICS && usage)
578c0a68be4Smrg usage->m_nsearches++;
579c0a68be4Smrg
580c0a68be4Smrg bitmap_element *element = bitmap_tree_splay (head, head->first, indx);
581c0a68be4Smrg gcc_checking_assert (element != NULL);
582c0a68be4Smrg head->first = element;
583c0a68be4Smrg head->current = element;
584c0a68be4Smrg head->indx = element->indx;
585c0a68be4Smrg if (element->indx != indx)
586c0a68be4Smrg element = 0;
587c0a68be4Smrg return element;
588c0a68be4Smrg }
589c0a68be4Smrg
590c0a68be4Smrg /* Converting bitmap views from linked-list to tree and vice versa. */
591c0a68be4Smrg
592c0a68be4Smrg /* Splice element E and all elements with a larger index from
593c0a68be4Smrg bitmap HEAD, convert the spliced elements to the linked-list
594c0a68be4Smrg view, and return the head of the list (which should be E again), */
595c0a68be4Smrg
596c0a68be4Smrg static bitmap_element *
bitmap_tree_listify_from(bitmap head,bitmap_element * e)597c0a68be4Smrg bitmap_tree_listify_from (bitmap head, bitmap_element *e)
598c0a68be4Smrg {
599c0a68be4Smrg bitmap_element *t, *erb;
600c0a68be4Smrg
601c0a68be4Smrg /* Detach the right branch from E (all elements with indx > E->indx),
602c0a68be4Smrg and splay E to the root. */
603c0a68be4Smrg erb = e->next;
604c0a68be4Smrg e->next = NULL;
605c0a68be4Smrg t = bitmap_tree_splay (head, head->first, e->indx);
606c0a68be4Smrg gcc_checking_assert (t == e);
607c0a68be4Smrg
608c0a68be4Smrg /* Because E has no right branch, and we rotated it to the root,
609c0a68be4Smrg the left branch is the new root. */
610c0a68be4Smrg t = e->prev;
611c0a68be4Smrg head->first = t;
612c0a68be4Smrg head->current = t;
613c0a68be4Smrg head->indx = (t != NULL) ? t->indx : 0;
614c0a68be4Smrg
615c0a68be4Smrg /* Detach the tree from E, and re-attach the right branch of E. */
616c0a68be4Smrg e->prev = NULL;
617c0a68be4Smrg e->next = erb;
618c0a68be4Smrg
619c0a68be4Smrg /* The tree is now valid again. Now we need to "un-tree" E.
620c0a68be4Smrg It is imperative that a non-recursive implementation is used
621c0a68be4Smrg for this, because splay trees have a worst case depth of O(N)
622c0a68be4Smrg for a tree with N nodes. A recursive implementation could
623c0a68be4Smrg result in a stack overflow for a sufficiently large, unbalanced
624c0a68be4Smrg bitmap tree. */
625c0a68be4Smrg
626c0a68be4Smrg auto_vec<bitmap_element *, 32> stack;
627c0a68be4Smrg auto_vec<bitmap_element *, 32> sorted_elements;
628c0a68be4Smrg bitmap_element *n = e;
629c0a68be4Smrg
630c0a68be4Smrg while (true)
631c0a68be4Smrg {
632c0a68be4Smrg while (n != NULL)
633c0a68be4Smrg {
634c0a68be4Smrg stack.safe_push (n);
635c0a68be4Smrg n = n->prev;
636c0a68be4Smrg }
637c0a68be4Smrg
638c0a68be4Smrg if (stack.is_empty ())
639c0a68be4Smrg break;
640c0a68be4Smrg
641c0a68be4Smrg n = stack.pop ();
642c0a68be4Smrg sorted_elements.safe_push (n);
643c0a68be4Smrg n = n->next;
644c0a68be4Smrg }
645c0a68be4Smrg
646c0a68be4Smrg gcc_assert (sorted_elements[0] == e);
647c0a68be4Smrg
648c0a68be4Smrg bitmap_element *prev = NULL;
649c0a68be4Smrg unsigned ix;
650c0a68be4Smrg FOR_EACH_VEC_ELT (sorted_elements, ix, n)
651c0a68be4Smrg {
652c0a68be4Smrg if (prev != NULL)
653c0a68be4Smrg prev->next = n;
654c0a68be4Smrg n->prev = prev;
655c0a68be4Smrg n->next = NULL;
656c0a68be4Smrg prev = n;
657c0a68be4Smrg }
658c0a68be4Smrg
659c0a68be4Smrg return e;
660c0a68be4Smrg }
661c0a68be4Smrg
662c0a68be4Smrg /* Convert bitmap HEAD from splay-tree view to linked-list view. */
663c0a68be4Smrg
664c0a68be4Smrg void
bitmap_list_view(bitmap head)665c0a68be4Smrg bitmap_list_view (bitmap head)
666c0a68be4Smrg {
667c0a68be4Smrg bitmap_element *ptr;
668c0a68be4Smrg
669c0a68be4Smrg gcc_assert (head->tree_form);
670c0a68be4Smrg
671c0a68be4Smrg ptr = head->first;
672c0a68be4Smrg if (ptr)
673c0a68be4Smrg {
674c0a68be4Smrg while (ptr->prev)
675c0a68be4Smrg bitmap_tree_rotate_right (ptr);
676c0a68be4Smrg head->first = ptr;
677c0a68be4Smrg head->first = bitmap_tree_listify_from (head, ptr);
678c0a68be4Smrg }
679c0a68be4Smrg
680c0a68be4Smrg head->tree_form = false;
681c0a68be4Smrg }
682c0a68be4Smrg
683c0a68be4Smrg /* Convert bitmap HEAD from linked-list view to splay-tree view.
684c0a68be4Smrg This is simply a matter of dropping the prev or next pointers
685c0a68be4Smrg and setting the tree_form flag. The tree will balance itself
686c0a68be4Smrg if and when it is used. */
687c0a68be4Smrg
688c0a68be4Smrg void
bitmap_tree_view(bitmap head)689c0a68be4Smrg bitmap_tree_view (bitmap head)
690c0a68be4Smrg {
691c0a68be4Smrg bitmap_element *ptr;
692c0a68be4Smrg
693c0a68be4Smrg gcc_assert (! head->tree_form);
694c0a68be4Smrg
695c0a68be4Smrg ptr = head->first;
696c0a68be4Smrg while (ptr)
697c0a68be4Smrg {
698c0a68be4Smrg ptr->prev = NULL;
699c0a68be4Smrg ptr = ptr->next;
700c0a68be4Smrg }
701c0a68be4Smrg
702c0a68be4Smrg head->tree_form = true;
703c0a68be4Smrg }
704c0a68be4Smrg
705c0a68be4Smrg /* Clear a bitmap by freeing all its elements. */
7061debfc3dSmrg
7071debfc3dSmrg void
bitmap_clear(bitmap head)7081debfc3dSmrg bitmap_clear (bitmap head)
7091debfc3dSmrg {
710c0a68be4Smrg if (head->first == NULL)
711c0a68be4Smrg return;
712c0a68be4Smrg if (head->tree_form)
713c0a68be4Smrg {
714c0a68be4Smrg bitmap_element *e, *t;
715c0a68be4Smrg for (e = head->first; e->prev; e = e->prev)
716c0a68be4Smrg /* Loop to find the element with the smallest index. */ ;
717c0a68be4Smrg t = bitmap_tree_splay (head, head->first, e->indx);
718c0a68be4Smrg gcc_checking_assert (t == e);
719c0a68be4Smrg head->first = t;
720c0a68be4Smrg }
7211debfc3dSmrg bitmap_elt_clear_from (head, head->first);
7221debfc3dSmrg }
7231debfc3dSmrg
7241debfc3dSmrg /* Initialize a bitmap obstack. If BIT_OBSTACK is NULL, initialize
7251debfc3dSmrg the default bitmap obstack. */
7261debfc3dSmrg
7271debfc3dSmrg void
bitmap_obstack_initialize(bitmap_obstack * bit_obstack)7281debfc3dSmrg bitmap_obstack_initialize (bitmap_obstack *bit_obstack)
7291debfc3dSmrg {
7301debfc3dSmrg if (!bit_obstack)
7311debfc3dSmrg {
7321debfc3dSmrg if (bitmap_default_obstack_depth++)
7331debfc3dSmrg return;
7341debfc3dSmrg bit_obstack = &bitmap_default_obstack;
7351debfc3dSmrg }
7361debfc3dSmrg
7371debfc3dSmrg #if !defined(__GNUC__) || (__GNUC__ < 2)
7381debfc3dSmrg #define __alignof__(type) 0
7391debfc3dSmrg #endif
7401debfc3dSmrg
7411debfc3dSmrg bit_obstack->elements = NULL;
7421debfc3dSmrg bit_obstack->heads = NULL;
7431debfc3dSmrg obstack_specify_allocation (&bit_obstack->obstack, OBSTACK_CHUNK_SIZE,
7441debfc3dSmrg __alignof__ (bitmap_element),
7451debfc3dSmrg obstack_chunk_alloc,
7461debfc3dSmrg obstack_chunk_free);
7471debfc3dSmrg }
7481debfc3dSmrg
7491debfc3dSmrg /* Release the memory from a bitmap obstack. If BIT_OBSTACK is NULL,
7501debfc3dSmrg release the default bitmap obstack. */
7511debfc3dSmrg
7521debfc3dSmrg void
bitmap_obstack_release(bitmap_obstack * bit_obstack)7531debfc3dSmrg bitmap_obstack_release (bitmap_obstack *bit_obstack)
7541debfc3dSmrg {
7551debfc3dSmrg if (!bit_obstack)
7561debfc3dSmrg {
7571debfc3dSmrg if (--bitmap_default_obstack_depth)
7581debfc3dSmrg {
7591debfc3dSmrg gcc_assert (bitmap_default_obstack_depth > 0);
7601debfc3dSmrg return;
7611debfc3dSmrg }
7621debfc3dSmrg bit_obstack = &bitmap_default_obstack;
7631debfc3dSmrg }
7641debfc3dSmrg
7651debfc3dSmrg bit_obstack->elements = NULL;
7661debfc3dSmrg bit_obstack->heads = NULL;
7671debfc3dSmrg obstack_free (&bit_obstack->obstack, NULL);
7681debfc3dSmrg }
7691debfc3dSmrg
7701debfc3dSmrg /* Create a new bitmap on an obstack. If BIT_OBSTACK is NULL, create
7711debfc3dSmrg it on the default bitmap obstack. */
7721debfc3dSmrg
7731debfc3dSmrg bitmap
bitmap_alloc(bitmap_obstack * bit_obstack MEM_STAT_DECL)774a2dc1f3fSmrg bitmap_alloc (bitmap_obstack *bit_obstack MEM_STAT_DECL)
7751debfc3dSmrg {
7761debfc3dSmrg bitmap map;
7771debfc3dSmrg
7781debfc3dSmrg if (!bit_obstack)
7791debfc3dSmrg bit_obstack = &bitmap_default_obstack;
7801debfc3dSmrg map = bit_obstack->heads;
7811debfc3dSmrg if (map)
782*8feb0f0bSmrg bit_obstack->heads = (class bitmap_head *) map->first;
7831debfc3dSmrg else
7841debfc3dSmrg map = XOBNEW (&bit_obstack->obstack, bitmap_head);
785a2dc1f3fSmrg bitmap_initialize (map, bit_obstack PASS_MEM_STAT);
7861debfc3dSmrg
7871debfc3dSmrg if (GATHER_STATISTICS)
7881debfc3dSmrg register_overhead (map, sizeof (bitmap_head));
7891debfc3dSmrg
7901debfc3dSmrg return map;
7911debfc3dSmrg }
7921debfc3dSmrg
7931debfc3dSmrg /* Create a new GCd bitmap. */
7941debfc3dSmrg
7951debfc3dSmrg bitmap
bitmap_gc_alloc(ALONE_MEM_STAT_DECL)796a2dc1f3fSmrg bitmap_gc_alloc (ALONE_MEM_STAT_DECL)
7971debfc3dSmrg {
7981debfc3dSmrg bitmap map;
7991debfc3dSmrg
8001debfc3dSmrg map = ggc_alloc<bitmap_head> ();
801a2dc1f3fSmrg bitmap_initialize (map, NULL PASS_MEM_STAT);
8021debfc3dSmrg
8031debfc3dSmrg if (GATHER_STATISTICS)
8041debfc3dSmrg register_overhead (map, sizeof (bitmap_head));
8051debfc3dSmrg
8061debfc3dSmrg return map;
8071debfc3dSmrg }
8081debfc3dSmrg
8091debfc3dSmrg /* Release an obstack allocated bitmap. */
8101debfc3dSmrg
8111debfc3dSmrg void
bitmap_obstack_free(bitmap map)8121debfc3dSmrg bitmap_obstack_free (bitmap map)
8131debfc3dSmrg {
8141debfc3dSmrg if (map)
8151debfc3dSmrg {
8161debfc3dSmrg bitmap_clear (map);
8171debfc3dSmrg map->first = (bitmap_element *) map->obstack->heads;
8181debfc3dSmrg
8191debfc3dSmrg if (GATHER_STATISTICS)
820*8feb0f0bSmrg release_overhead (map, sizeof (bitmap_head), true);
8211debfc3dSmrg
8221debfc3dSmrg map->obstack->heads = map;
8231debfc3dSmrg }
8241debfc3dSmrg }
8251debfc3dSmrg
8261debfc3dSmrg
8271debfc3dSmrg /* Return nonzero if all bits in an element are zero. */
8281debfc3dSmrg
8291debfc3dSmrg static inline int
bitmap_element_zerop(const bitmap_element * element)8301debfc3dSmrg bitmap_element_zerop (const bitmap_element *element)
8311debfc3dSmrg {
8321debfc3dSmrg #if BITMAP_ELEMENT_WORDS == 2
8331debfc3dSmrg return (element->bits[0] | element->bits[1]) == 0;
8341debfc3dSmrg #else
8351debfc3dSmrg unsigned i;
8361debfc3dSmrg
8371debfc3dSmrg for (i = 0; i < BITMAP_ELEMENT_WORDS; i++)
8381debfc3dSmrg if (element->bits[i] != 0)
8391debfc3dSmrg return 0;
8401debfc3dSmrg
8411debfc3dSmrg return 1;
8421debfc3dSmrg #endif
8431debfc3dSmrg }
8441debfc3dSmrg
8451debfc3dSmrg /* Copy a bitmap to another bitmap. */
8461debfc3dSmrg
8471debfc3dSmrg void
bitmap_copy(bitmap to,const_bitmap from)8481debfc3dSmrg bitmap_copy (bitmap to, const_bitmap from)
8491debfc3dSmrg {
8501debfc3dSmrg const bitmap_element *from_ptr;
8511debfc3dSmrg bitmap_element *to_ptr = 0;
8521debfc3dSmrg
853c0a68be4Smrg gcc_checking_assert (!to->tree_form && !from->tree_form);
854c0a68be4Smrg
8551debfc3dSmrg bitmap_clear (to);
8561debfc3dSmrg
8571debfc3dSmrg /* Copy elements in forward direction one at a time. */
8581debfc3dSmrg for (from_ptr = from->first; from_ptr; from_ptr = from_ptr->next)
8591debfc3dSmrg {
8601debfc3dSmrg bitmap_element *to_elt = bitmap_element_allocate (to);
8611debfc3dSmrg
8621debfc3dSmrg to_elt->indx = from_ptr->indx;
8631debfc3dSmrg memcpy (to_elt->bits, from_ptr->bits, sizeof (to_elt->bits));
8641debfc3dSmrg
865c0a68be4Smrg /* Here we have a special case of bitmap_list_link_element,
866c0a68be4Smrg for the case where we know the links are being entered
867c0a68be4Smrg in sequence. */
8681debfc3dSmrg if (to_ptr == 0)
8691debfc3dSmrg {
8701debfc3dSmrg to->first = to->current = to_elt;
8711debfc3dSmrg to->indx = from_ptr->indx;
8721debfc3dSmrg to_elt->next = to_elt->prev = 0;
8731debfc3dSmrg }
8741debfc3dSmrg else
8751debfc3dSmrg {
8761debfc3dSmrg to_elt->prev = to_ptr;
8771debfc3dSmrg to_elt->next = 0;
8781debfc3dSmrg to_ptr->next = to_elt;
8791debfc3dSmrg }
8801debfc3dSmrg
8811debfc3dSmrg to_ptr = to_elt;
8821debfc3dSmrg }
8831debfc3dSmrg }
8841debfc3dSmrg
8851debfc3dSmrg /* Move a bitmap to another bitmap. */
8861debfc3dSmrg
8871debfc3dSmrg void
bitmap_move(bitmap to,bitmap from)8881debfc3dSmrg bitmap_move (bitmap to, bitmap from)
8891debfc3dSmrg {
8901debfc3dSmrg gcc_assert (to->obstack == from->obstack);
8911debfc3dSmrg
8921debfc3dSmrg bitmap_clear (to);
8931debfc3dSmrg
894*8feb0f0bSmrg size_t sz = 0;
8951debfc3dSmrg if (GATHER_STATISTICS)
8961debfc3dSmrg {
8971debfc3dSmrg for (bitmap_element *e = to->first; e; e = e->next)
8981debfc3dSmrg sz += sizeof (bitmap_element);
8991debfc3dSmrg register_overhead (to, sz);
9001debfc3dSmrg }
901*8feb0f0bSmrg
902*8feb0f0bSmrg *to = *from;
903*8feb0f0bSmrg
904*8feb0f0bSmrg if (GATHER_STATISTICS)
905*8feb0f0bSmrg release_overhead (from, sz, false);
9061debfc3dSmrg }
9071debfc3dSmrg
9081debfc3dSmrg /* Clear a single bit in a bitmap. Return true if the bit changed. */
9091debfc3dSmrg
9101debfc3dSmrg bool
bitmap_clear_bit(bitmap head,int bit)9111debfc3dSmrg bitmap_clear_bit (bitmap head, int bit)
9121debfc3dSmrg {
913c0a68be4Smrg unsigned int indx = bit / BITMAP_ELEMENT_ALL_BITS;
914c0a68be4Smrg bitmap_element *ptr;
9151debfc3dSmrg
916c0a68be4Smrg if (!head->tree_form)
917c0a68be4Smrg ptr = bitmap_list_find_element (head, indx);
918c0a68be4Smrg else
919c0a68be4Smrg ptr = bitmap_tree_find_element (head, indx);
9201debfc3dSmrg if (ptr != 0)
9211debfc3dSmrg {
9221debfc3dSmrg unsigned bit_num = bit % BITMAP_WORD_BITS;
9231debfc3dSmrg unsigned word_num = bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS;
9241debfc3dSmrg BITMAP_WORD bit_val = ((BITMAP_WORD) 1) << bit_num;
9251debfc3dSmrg bool res = (ptr->bits[word_num] & bit_val) != 0;
9261debfc3dSmrg if (res)
9271debfc3dSmrg {
9281debfc3dSmrg ptr->bits[word_num] &= ~bit_val;
9291debfc3dSmrg /* If we cleared the entire word, free up the element. */
9301debfc3dSmrg if (!ptr->bits[word_num]
9311debfc3dSmrg && bitmap_element_zerop (ptr))
932c0a68be4Smrg {
933c0a68be4Smrg if (!head->tree_form)
934c0a68be4Smrg bitmap_list_unlink_element (head, ptr);
935c0a68be4Smrg else
936c0a68be4Smrg bitmap_tree_unlink_element (head, ptr);
937c0a68be4Smrg }
9381debfc3dSmrg }
9391debfc3dSmrg
9401debfc3dSmrg return res;
9411debfc3dSmrg }
9421debfc3dSmrg
9431debfc3dSmrg return false;
9441debfc3dSmrg }
9451debfc3dSmrg
9461debfc3dSmrg /* Set a single bit in a bitmap. Return true if the bit changed. */
9471debfc3dSmrg
9481debfc3dSmrg bool
bitmap_set_bit(bitmap head,int bit)9491debfc3dSmrg bitmap_set_bit (bitmap head, int bit)
9501debfc3dSmrg {
951c0a68be4Smrg unsigned indx = bit / BITMAP_ELEMENT_ALL_BITS;
952c0a68be4Smrg bitmap_element *ptr;
953c0a68be4Smrg if (!head->tree_form)
954c0a68be4Smrg ptr = bitmap_list_find_element (head, indx);
955c0a68be4Smrg else
956c0a68be4Smrg ptr = bitmap_tree_find_element (head, indx);
9571debfc3dSmrg unsigned word_num = bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS;
9581debfc3dSmrg unsigned bit_num = bit % BITMAP_WORD_BITS;
9591debfc3dSmrg BITMAP_WORD bit_val = ((BITMAP_WORD) 1) << bit_num;
9601debfc3dSmrg
961c0a68be4Smrg if (ptr != 0)
9621debfc3dSmrg {
9631debfc3dSmrg bool res = (ptr->bits[word_num] & bit_val) == 0;
9641debfc3dSmrg if (res)
9651debfc3dSmrg ptr->bits[word_num] |= bit_val;
9661debfc3dSmrg return res;
9671debfc3dSmrg }
968c0a68be4Smrg
969c0a68be4Smrg ptr = bitmap_element_allocate (head);
970c0a68be4Smrg ptr->indx = bit / BITMAP_ELEMENT_ALL_BITS;
971c0a68be4Smrg ptr->bits[word_num] = bit_val;
972c0a68be4Smrg if (!head->tree_form)
973c0a68be4Smrg bitmap_list_link_element (head, ptr);
974c0a68be4Smrg else
975c0a68be4Smrg bitmap_tree_link_element (head, ptr);
976c0a68be4Smrg return true;
9771debfc3dSmrg }
9781debfc3dSmrg
9791debfc3dSmrg /* Return whether a bit is set within a bitmap. */
9801debfc3dSmrg
9811debfc3dSmrg int
bitmap_bit_p(const_bitmap head,int bit)982*8feb0f0bSmrg bitmap_bit_p (const_bitmap head, int bit)
9831debfc3dSmrg {
984c0a68be4Smrg unsigned int indx = bit / BITMAP_ELEMENT_ALL_BITS;
985*8feb0f0bSmrg const bitmap_element *ptr;
9861debfc3dSmrg unsigned bit_num;
9871debfc3dSmrg unsigned word_num;
9881debfc3dSmrg
989c0a68be4Smrg if (!head->tree_form)
990*8feb0f0bSmrg ptr = bitmap_list_find_element (const_cast<bitmap> (head), indx);
991c0a68be4Smrg else
992*8feb0f0bSmrg ptr = bitmap_tree_find_element (const_cast<bitmap> (head), indx);
9931debfc3dSmrg if (ptr == 0)
9941debfc3dSmrg return 0;
9951debfc3dSmrg
9961debfc3dSmrg bit_num = bit % BITMAP_WORD_BITS;
9971debfc3dSmrg word_num = bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS;
9981debfc3dSmrg
9991debfc3dSmrg return (ptr->bits[word_num] >> bit_num) & 1;
10001debfc3dSmrg }
10011debfc3dSmrg
10021debfc3dSmrg #if GCC_VERSION < 3400
10031debfc3dSmrg /* Table of number of set bits in a character, indexed by value of char. */
10041debfc3dSmrg static const unsigned char popcount_table[] =
10051debfc3dSmrg {
10061debfc3dSmrg 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
10071debfc3dSmrg 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
10081debfc3dSmrg 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
10091debfc3dSmrg 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
10101debfc3dSmrg 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
10111debfc3dSmrg 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
10121debfc3dSmrg 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
10131debfc3dSmrg 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
10141debfc3dSmrg };
10151debfc3dSmrg
10161debfc3dSmrg static unsigned long
bitmap_popcount(BITMAP_WORD a)10171debfc3dSmrg bitmap_popcount (BITMAP_WORD a)
10181debfc3dSmrg {
10191debfc3dSmrg unsigned long ret = 0;
10201debfc3dSmrg unsigned i;
10211debfc3dSmrg
10221debfc3dSmrg /* Just do this the table way for now */
10231debfc3dSmrg for (i = 0; i < BITMAP_WORD_BITS; i+= 8)
10241debfc3dSmrg ret += popcount_table[(a >> i) & 0xff];
10251debfc3dSmrg return ret;
10261debfc3dSmrg }
10271debfc3dSmrg #endif
10281debfc3dSmrg
10291debfc3dSmrg /* Count and return the number of bits set in the bitmap word BITS. */
10301debfc3dSmrg static unsigned long
bitmap_count_bits_in_word(const BITMAP_WORD * bits)10311debfc3dSmrg bitmap_count_bits_in_word (const BITMAP_WORD *bits)
10321debfc3dSmrg {
10331debfc3dSmrg unsigned long count = 0;
10341debfc3dSmrg
10351debfc3dSmrg for (unsigned ix = 0; ix != BITMAP_ELEMENT_WORDS; ix++)
10361debfc3dSmrg {
10371debfc3dSmrg #if GCC_VERSION >= 3400
10381debfc3dSmrg /* Note that popcountl matches BITMAP_WORD in type, so the actual size
10391debfc3dSmrg of BITMAP_WORD is not material. */
10401debfc3dSmrg count += __builtin_popcountl (bits[ix]);
10411debfc3dSmrg #else
10421debfc3dSmrg count += bitmap_popcount (bits[ix]);
10431debfc3dSmrg #endif
10441debfc3dSmrg }
10451debfc3dSmrg return count;
10461debfc3dSmrg }
10471debfc3dSmrg
10481debfc3dSmrg /* Count the number of bits set in the bitmap, and return it. */
10491debfc3dSmrg
10501debfc3dSmrg unsigned long
bitmap_count_bits(const_bitmap a)10511debfc3dSmrg bitmap_count_bits (const_bitmap a)
10521debfc3dSmrg {
10531debfc3dSmrg unsigned long count = 0;
10541debfc3dSmrg const bitmap_element *elt;
10551debfc3dSmrg
1056c0a68be4Smrg gcc_checking_assert (!a->tree_form);
10571debfc3dSmrg for (elt = a->first; elt; elt = elt->next)
10581debfc3dSmrg count += bitmap_count_bits_in_word (elt->bits);
10591debfc3dSmrg
10601debfc3dSmrg return count;
10611debfc3dSmrg }
10621debfc3dSmrg
10631debfc3dSmrg /* Count the number of unique bits set in A and B and return it. */
10641debfc3dSmrg
10651debfc3dSmrg unsigned long
bitmap_count_unique_bits(const_bitmap a,const_bitmap b)10661debfc3dSmrg bitmap_count_unique_bits (const_bitmap a, const_bitmap b)
10671debfc3dSmrg {
10681debfc3dSmrg unsigned long count = 0;
10691debfc3dSmrg const bitmap_element *elt_a, *elt_b;
10701debfc3dSmrg
10711debfc3dSmrg for (elt_a = a->first, elt_b = b->first; elt_a && elt_b; )
10721debfc3dSmrg {
10731debfc3dSmrg /* If we're at different indices, then count all the bits
10741debfc3dSmrg in the lower element. If we're at the same index, then
10751debfc3dSmrg count the bits in the IOR of the two elements. */
10761debfc3dSmrg if (elt_a->indx < elt_b->indx)
10771debfc3dSmrg {
10781debfc3dSmrg count += bitmap_count_bits_in_word (elt_a->bits);
10791debfc3dSmrg elt_a = elt_a->next;
10801debfc3dSmrg }
10811debfc3dSmrg else if (elt_b->indx < elt_a->indx)
10821debfc3dSmrg {
10831debfc3dSmrg count += bitmap_count_bits_in_word (elt_b->bits);
10841debfc3dSmrg elt_b = elt_b->next;
10851debfc3dSmrg }
10861debfc3dSmrg else
10871debfc3dSmrg {
10881debfc3dSmrg BITMAP_WORD bits[BITMAP_ELEMENT_WORDS];
10891debfc3dSmrg for (unsigned ix = 0; ix != BITMAP_ELEMENT_WORDS; ix++)
10901debfc3dSmrg bits[ix] = elt_a->bits[ix] | elt_b->bits[ix];
10911debfc3dSmrg count += bitmap_count_bits_in_word (bits);
10921debfc3dSmrg elt_a = elt_a->next;
10931debfc3dSmrg elt_b = elt_b->next;
10941debfc3dSmrg }
10951debfc3dSmrg }
10961debfc3dSmrg return count;
10971debfc3dSmrg }
10981debfc3dSmrg
10991debfc3dSmrg /* Return true if the bitmap has a single bit set. Otherwise return
11001debfc3dSmrg false. */
11011debfc3dSmrg
11021debfc3dSmrg bool
bitmap_single_bit_set_p(const_bitmap a)11031debfc3dSmrg bitmap_single_bit_set_p (const_bitmap a)
11041debfc3dSmrg {
11051debfc3dSmrg unsigned long count = 0;
11061debfc3dSmrg const bitmap_element *elt;
11071debfc3dSmrg unsigned ix;
11081debfc3dSmrg
11091debfc3dSmrg if (bitmap_empty_p (a))
11101debfc3dSmrg return false;
11111debfc3dSmrg
11121debfc3dSmrg elt = a->first;
1113c0a68be4Smrg
11141debfc3dSmrg /* As there are no completely empty bitmap elements, a second one
11151debfc3dSmrg means we have more than one bit set. */
1116c0a68be4Smrg if (elt->next != NULL
1117c0a68be4Smrg && (!a->tree_form || elt->prev != NULL))
11181debfc3dSmrg return false;
11191debfc3dSmrg
11201debfc3dSmrg for (ix = 0; ix != BITMAP_ELEMENT_WORDS; ix++)
11211debfc3dSmrg {
11221debfc3dSmrg #if GCC_VERSION >= 3400
11231debfc3dSmrg /* Note that popcountl matches BITMAP_WORD in type, so the actual size
11241debfc3dSmrg of BITMAP_WORD is not material. */
11251debfc3dSmrg count += __builtin_popcountl (elt->bits[ix]);
11261debfc3dSmrg #else
11271debfc3dSmrg count += bitmap_popcount (elt->bits[ix]);
11281debfc3dSmrg #endif
11291debfc3dSmrg if (count > 1)
11301debfc3dSmrg return false;
11311debfc3dSmrg }
11321debfc3dSmrg
11331debfc3dSmrg return count == 1;
11341debfc3dSmrg }
11351debfc3dSmrg
11361debfc3dSmrg
11371debfc3dSmrg /* Return the bit number of the first set bit in the bitmap. The
11381debfc3dSmrg bitmap must be non-empty. */
11391debfc3dSmrg
11401debfc3dSmrg unsigned
bitmap_first_set_bit(const_bitmap a)11411debfc3dSmrg bitmap_first_set_bit (const_bitmap a)
11421debfc3dSmrg {
11431debfc3dSmrg const bitmap_element *elt = a->first;
11441debfc3dSmrg unsigned bit_no;
11451debfc3dSmrg BITMAP_WORD word;
11461debfc3dSmrg unsigned ix;
11471debfc3dSmrg
11481debfc3dSmrg gcc_checking_assert (elt);
1149c0a68be4Smrg
1150c0a68be4Smrg if (a->tree_form)
1151c0a68be4Smrg while (elt->prev)
1152c0a68be4Smrg elt = elt->prev;
1153c0a68be4Smrg
11541debfc3dSmrg bit_no = elt->indx * BITMAP_ELEMENT_ALL_BITS;
11551debfc3dSmrg for (ix = 0; ix != BITMAP_ELEMENT_WORDS; ix++)
11561debfc3dSmrg {
11571debfc3dSmrg word = elt->bits[ix];
11581debfc3dSmrg if (word)
11591debfc3dSmrg goto found_bit;
11601debfc3dSmrg }
11611debfc3dSmrg gcc_unreachable ();
11621debfc3dSmrg found_bit:
11631debfc3dSmrg bit_no += ix * BITMAP_WORD_BITS;
11641debfc3dSmrg
11651debfc3dSmrg #if GCC_VERSION >= 3004
11661debfc3dSmrg gcc_assert (sizeof (long) == sizeof (word));
11671debfc3dSmrg bit_no += __builtin_ctzl (word);
11681debfc3dSmrg #else
11691debfc3dSmrg /* Binary search for the first set bit. */
11701debfc3dSmrg #if BITMAP_WORD_BITS > 64
11711debfc3dSmrg #error "Fill out the table."
11721debfc3dSmrg #endif
11731debfc3dSmrg #if BITMAP_WORD_BITS > 32
11741debfc3dSmrg if (!(word & 0xffffffff))
11751debfc3dSmrg word >>= 32, bit_no += 32;
11761debfc3dSmrg #endif
11771debfc3dSmrg if (!(word & 0xffff))
11781debfc3dSmrg word >>= 16, bit_no += 16;
11791debfc3dSmrg if (!(word & 0xff))
11801debfc3dSmrg word >>= 8, bit_no += 8;
11811debfc3dSmrg if (!(word & 0xf))
11821debfc3dSmrg word >>= 4, bit_no += 4;
11831debfc3dSmrg if (!(word & 0x3))
11841debfc3dSmrg word >>= 2, bit_no += 2;
11851debfc3dSmrg if (!(word & 0x1))
11861debfc3dSmrg word >>= 1, bit_no += 1;
11871debfc3dSmrg
11881debfc3dSmrg gcc_checking_assert (word & 1);
11891debfc3dSmrg #endif
11901debfc3dSmrg return bit_no;
11911debfc3dSmrg }
11921debfc3dSmrg
11931debfc3dSmrg /* Return the bit number of the first set bit in the bitmap. The
11941debfc3dSmrg bitmap must be non-empty. */
11951debfc3dSmrg
11961debfc3dSmrg unsigned
bitmap_last_set_bit(const_bitmap a)11971debfc3dSmrg bitmap_last_set_bit (const_bitmap a)
11981debfc3dSmrg {
1199c0a68be4Smrg const bitmap_element *elt;
12001debfc3dSmrg unsigned bit_no;
12011debfc3dSmrg BITMAP_WORD word;
12021debfc3dSmrg int ix;
12031debfc3dSmrg
1204c0a68be4Smrg if (a->tree_form)
1205c0a68be4Smrg elt = a->first;
1206c0a68be4Smrg else
1207c0a68be4Smrg elt = a->current ? a->current : a->first;
12081debfc3dSmrg gcc_checking_assert (elt);
1209c0a68be4Smrg
12101debfc3dSmrg while (elt->next)
12111debfc3dSmrg elt = elt->next;
1212c0a68be4Smrg
12131debfc3dSmrg bit_no = elt->indx * BITMAP_ELEMENT_ALL_BITS;
1214c0a68be4Smrg for (ix = BITMAP_ELEMENT_WORDS - 1; ix >= 1; ix--)
12151debfc3dSmrg {
12161debfc3dSmrg word = elt->bits[ix];
12171debfc3dSmrg if (word)
12181debfc3dSmrg goto found_bit;
12191debfc3dSmrg }
1220c0a68be4Smrg gcc_assert (elt->bits[ix] != 0);
12211debfc3dSmrg found_bit:
12221debfc3dSmrg bit_no += ix * BITMAP_WORD_BITS;
12231debfc3dSmrg #if GCC_VERSION >= 3004
12241debfc3dSmrg gcc_assert (sizeof (long) == sizeof (word));
12251debfc3dSmrg bit_no += BITMAP_WORD_BITS - __builtin_clzl (word) - 1;
12261debfc3dSmrg #else
12271debfc3dSmrg /* Hopefully this is a twos-complement host... */
12281debfc3dSmrg BITMAP_WORD x = word;
12291debfc3dSmrg x |= (x >> 1);
12301debfc3dSmrg x |= (x >> 2);
12311debfc3dSmrg x |= (x >> 4);
12321debfc3dSmrg x |= (x >> 8);
12331debfc3dSmrg x |= (x >> 16);
12341debfc3dSmrg #if BITMAP_WORD_BITS > 32
12351debfc3dSmrg x |= (x >> 32);
12361debfc3dSmrg #endif
12371debfc3dSmrg bit_no += bitmap_popcount (x) - 1;
12381debfc3dSmrg #endif
12391debfc3dSmrg
12401debfc3dSmrg return bit_no;
12411debfc3dSmrg }
12421debfc3dSmrg
12431debfc3dSmrg
12441debfc3dSmrg /* DST = A & B. */
12451debfc3dSmrg
12461debfc3dSmrg void
bitmap_and(bitmap dst,const_bitmap a,const_bitmap b)12471debfc3dSmrg bitmap_and (bitmap dst, const_bitmap a, const_bitmap b)
12481debfc3dSmrg {
12491debfc3dSmrg bitmap_element *dst_elt = dst->first;
12501debfc3dSmrg const bitmap_element *a_elt = a->first;
12511debfc3dSmrg const bitmap_element *b_elt = b->first;
12521debfc3dSmrg bitmap_element *dst_prev = NULL;
12531debfc3dSmrg
1254c0a68be4Smrg gcc_checking_assert (!dst->tree_form && !a->tree_form && !b->tree_form);
12551debfc3dSmrg gcc_assert (dst != a && dst != b);
12561debfc3dSmrg
12571debfc3dSmrg if (a == b)
12581debfc3dSmrg {
12591debfc3dSmrg bitmap_copy (dst, a);
12601debfc3dSmrg return;
12611debfc3dSmrg }
12621debfc3dSmrg
12631debfc3dSmrg while (a_elt && b_elt)
12641debfc3dSmrg {
12651debfc3dSmrg if (a_elt->indx < b_elt->indx)
12661debfc3dSmrg a_elt = a_elt->next;
12671debfc3dSmrg else if (b_elt->indx < a_elt->indx)
12681debfc3dSmrg b_elt = b_elt->next;
12691debfc3dSmrg else
12701debfc3dSmrg {
12711debfc3dSmrg /* Matching elts, generate A & B. */
12721debfc3dSmrg unsigned ix;
12731debfc3dSmrg BITMAP_WORD ior = 0;
12741debfc3dSmrg
12751debfc3dSmrg if (!dst_elt)
1276c0a68be4Smrg dst_elt = bitmap_list_insert_element_after (dst, dst_prev,
1277c0a68be4Smrg a_elt->indx);
12781debfc3dSmrg else
12791debfc3dSmrg dst_elt->indx = a_elt->indx;
12801debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
12811debfc3dSmrg {
12821debfc3dSmrg BITMAP_WORD r = a_elt->bits[ix] & b_elt->bits[ix];
12831debfc3dSmrg
12841debfc3dSmrg dst_elt->bits[ix] = r;
12851debfc3dSmrg ior |= r;
12861debfc3dSmrg }
12871debfc3dSmrg if (ior)
12881debfc3dSmrg {
12891debfc3dSmrg dst_prev = dst_elt;
12901debfc3dSmrg dst_elt = dst_elt->next;
12911debfc3dSmrg }
12921debfc3dSmrg a_elt = a_elt->next;
12931debfc3dSmrg b_elt = b_elt->next;
12941debfc3dSmrg }
12951debfc3dSmrg }
12961debfc3dSmrg /* Ensure that dst->current is valid. */
12971debfc3dSmrg dst->current = dst->first;
12981debfc3dSmrg bitmap_elt_clear_from (dst, dst_elt);
12991debfc3dSmrg gcc_checking_assert (!dst->current == !dst->first);
13001debfc3dSmrg if (dst->current)
13011debfc3dSmrg dst->indx = dst->current->indx;
13021debfc3dSmrg }
13031debfc3dSmrg
13041debfc3dSmrg /* A &= B. Return true if A changed. */
13051debfc3dSmrg
13061debfc3dSmrg bool
bitmap_and_into(bitmap a,const_bitmap b)13071debfc3dSmrg bitmap_and_into (bitmap a, const_bitmap b)
13081debfc3dSmrg {
13091debfc3dSmrg bitmap_element *a_elt = a->first;
13101debfc3dSmrg const bitmap_element *b_elt = b->first;
13111debfc3dSmrg bitmap_element *next;
13121debfc3dSmrg bool changed = false;
13131debfc3dSmrg
1314c0a68be4Smrg gcc_checking_assert (!a->tree_form && !b->tree_form);
1315c0a68be4Smrg
13161debfc3dSmrg if (a == b)
13171debfc3dSmrg return false;
13181debfc3dSmrg
13191debfc3dSmrg while (a_elt && b_elt)
13201debfc3dSmrg {
13211debfc3dSmrg if (a_elt->indx < b_elt->indx)
13221debfc3dSmrg {
13231debfc3dSmrg next = a_elt->next;
1324c0a68be4Smrg bitmap_list_unlink_element (a, a_elt);
13251debfc3dSmrg a_elt = next;
13261debfc3dSmrg changed = true;
13271debfc3dSmrg }
13281debfc3dSmrg else if (b_elt->indx < a_elt->indx)
13291debfc3dSmrg b_elt = b_elt->next;
13301debfc3dSmrg else
13311debfc3dSmrg {
13321debfc3dSmrg /* Matching elts, generate A &= B. */
13331debfc3dSmrg unsigned ix;
13341debfc3dSmrg BITMAP_WORD ior = 0;
13351debfc3dSmrg
13361debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
13371debfc3dSmrg {
13381debfc3dSmrg BITMAP_WORD r = a_elt->bits[ix] & b_elt->bits[ix];
13391debfc3dSmrg if (a_elt->bits[ix] != r)
13401debfc3dSmrg changed = true;
13411debfc3dSmrg a_elt->bits[ix] = r;
13421debfc3dSmrg ior |= r;
13431debfc3dSmrg }
13441debfc3dSmrg next = a_elt->next;
13451debfc3dSmrg if (!ior)
1346c0a68be4Smrg bitmap_list_unlink_element (a, a_elt);
13471debfc3dSmrg a_elt = next;
13481debfc3dSmrg b_elt = b_elt->next;
13491debfc3dSmrg }
13501debfc3dSmrg }
13511debfc3dSmrg
13521debfc3dSmrg if (a_elt)
13531debfc3dSmrg {
13541debfc3dSmrg changed = true;
13551debfc3dSmrg bitmap_elt_clear_from (a, a_elt);
13561debfc3dSmrg }
13571debfc3dSmrg
13581debfc3dSmrg gcc_checking_assert (!a->current == !a->first
13591debfc3dSmrg && (!a->current || a->indx == a->current->indx));
13601debfc3dSmrg
13611debfc3dSmrg return changed;
13621debfc3dSmrg }
13631debfc3dSmrg
13641debfc3dSmrg
13651debfc3dSmrg /* Insert an element equal to SRC_ELT after DST_PREV, overwriting DST_ELT
13661debfc3dSmrg if non-NULL. CHANGED is true if the destination bitmap had already been
13671debfc3dSmrg changed; the new value of CHANGED is returned. */
13681debfc3dSmrg
13691debfc3dSmrg static inline bool
bitmap_elt_copy(bitmap dst,bitmap_element * dst_elt,bitmap_element * dst_prev,const bitmap_element * src_elt,bool changed)13701debfc3dSmrg bitmap_elt_copy (bitmap dst, bitmap_element *dst_elt, bitmap_element *dst_prev,
13711debfc3dSmrg const bitmap_element *src_elt, bool changed)
13721debfc3dSmrg {
13731debfc3dSmrg if (!changed && dst_elt && dst_elt->indx == src_elt->indx)
13741debfc3dSmrg {
13751debfc3dSmrg unsigned ix;
13761debfc3dSmrg
13771debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
13781debfc3dSmrg if (src_elt->bits[ix] != dst_elt->bits[ix])
13791debfc3dSmrg {
13801debfc3dSmrg dst_elt->bits[ix] = src_elt->bits[ix];
13811debfc3dSmrg changed = true;
13821debfc3dSmrg }
13831debfc3dSmrg }
13841debfc3dSmrg else
13851debfc3dSmrg {
13861debfc3dSmrg changed = true;
13871debfc3dSmrg if (!dst_elt)
1388c0a68be4Smrg dst_elt = bitmap_list_insert_element_after (dst, dst_prev,
1389c0a68be4Smrg src_elt->indx);
13901debfc3dSmrg else
13911debfc3dSmrg dst_elt->indx = src_elt->indx;
13921debfc3dSmrg memcpy (dst_elt->bits, src_elt->bits, sizeof (dst_elt->bits));
13931debfc3dSmrg }
13941debfc3dSmrg return changed;
13951debfc3dSmrg }
13961debfc3dSmrg
13971debfc3dSmrg
13981debfc3dSmrg
13991debfc3dSmrg /* DST = A & ~B */
14001debfc3dSmrg
14011debfc3dSmrg bool
bitmap_and_compl(bitmap dst,const_bitmap a,const_bitmap b)14021debfc3dSmrg bitmap_and_compl (bitmap dst, const_bitmap a, const_bitmap b)
14031debfc3dSmrg {
14041debfc3dSmrg bitmap_element *dst_elt = dst->first;
14051debfc3dSmrg const bitmap_element *a_elt = a->first;
14061debfc3dSmrg const bitmap_element *b_elt = b->first;
14071debfc3dSmrg bitmap_element *dst_prev = NULL;
14081debfc3dSmrg bitmap_element **dst_prev_pnext = &dst->first;
14091debfc3dSmrg bool changed = false;
14101debfc3dSmrg
1411c0a68be4Smrg gcc_checking_assert (!dst->tree_form && !a->tree_form && !b->tree_form);
14121debfc3dSmrg gcc_assert (dst != a && dst != b);
14131debfc3dSmrg
14141debfc3dSmrg if (a == b)
14151debfc3dSmrg {
14161debfc3dSmrg changed = !bitmap_empty_p (dst);
14171debfc3dSmrg bitmap_clear (dst);
14181debfc3dSmrg return changed;
14191debfc3dSmrg }
14201debfc3dSmrg
14211debfc3dSmrg while (a_elt)
14221debfc3dSmrg {
14231debfc3dSmrg while (b_elt && b_elt->indx < a_elt->indx)
14241debfc3dSmrg b_elt = b_elt->next;
14251debfc3dSmrg
14261debfc3dSmrg if (!b_elt || b_elt->indx > a_elt->indx)
14271debfc3dSmrg {
14281debfc3dSmrg changed = bitmap_elt_copy (dst, dst_elt, dst_prev, a_elt, changed);
14291debfc3dSmrg dst_prev = *dst_prev_pnext;
14301debfc3dSmrg dst_prev_pnext = &dst_prev->next;
14311debfc3dSmrg dst_elt = *dst_prev_pnext;
14321debfc3dSmrg a_elt = a_elt->next;
14331debfc3dSmrg }
14341debfc3dSmrg
14351debfc3dSmrg else
14361debfc3dSmrg {
14371debfc3dSmrg /* Matching elts, generate A & ~B. */
14381debfc3dSmrg unsigned ix;
14391debfc3dSmrg BITMAP_WORD ior = 0;
14401debfc3dSmrg
14411debfc3dSmrg if (!changed && dst_elt && dst_elt->indx == a_elt->indx)
14421debfc3dSmrg {
14431debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
14441debfc3dSmrg {
14451debfc3dSmrg BITMAP_WORD r = a_elt->bits[ix] & ~b_elt->bits[ix];
14461debfc3dSmrg
14471debfc3dSmrg if (dst_elt->bits[ix] != r)
14481debfc3dSmrg {
14491debfc3dSmrg changed = true;
14501debfc3dSmrg dst_elt->bits[ix] = r;
14511debfc3dSmrg }
14521debfc3dSmrg ior |= r;
14531debfc3dSmrg }
14541debfc3dSmrg }
14551debfc3dSmrg else
14561debfc3dSmrg {
14571debfc3dSmrg bool new_element;
14581debfc3dSmrg if (!dst_elt || dst_elt->indx > a_elt->indx)
14591debfc3dSmrg {
1460c0a68be4Smrg dst_elt = bitmap_list_insert_element_after (dst, dst_prev,
1461c0a68be4Smrg a_elt->indx);
14621debfc3dSmrg new_element = true;
14631debfc3dSmrg }
14641debfc3dSmrg else
14651debfc3dSmrg {
14661debfc3dSmrg dst_elt->indx = a_elt->indx;
14671debfc3dSmrg new_element = false;
14681debfc3dSmrg }
14691debfc3dSmrg
14701debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
14711debfc3dSmrg {
14721debfc3dSmrg BITMAP_WORD r = a_elt->bits[ix] & ~b_elt->bits[ix];
14731debfc3dSmrg
14741debfc3dSmrg dst_elt->bits[ix] = r;
14751debfc3dSmrg ior |= r;
14761debfc3dSmrg }
14771debfc3dSmrg
14781debfc3dSmrg if (ior)
14791debfc3dSmrg changed = true;
14801debfc3dSmrg else
14811debfc3dSmrg {
14821debfc3dSmrg changed |= !new_element;
1483c0a68be4Smrg bitmap_list_unlink_element (dst, dst_elt);
14841debfc3dSmrg dst_elt = *dst_prev_pnext;
14851debfc3dSmrg }
14861debfc3dSmrg }
14871debfc3dSmrg
14881debfc3dSmrg if (ior)
14891debfc3dSmrg {
14901debfc3dSmrg dst_prev = *dst_prev_pnext;
14911debfc3dSmrg dst_prev_pnext = &dst_prev->next;
14921debfc3dSmrg dst_elt = *dst_prev_pnext;
14931debfc3dSmrg }
14941debfc3dSmrg a_elt = a_elt->next;
14951debfc3dSmrg b_elt = b_elt->next;
14961debfc3dSmrg }
14971debfc3dSmrg }
14981debfc3dSmrg
14991debfc3dSmrg /* Ensure that dst->current is valid. */
15001debfc3dSmrg dst->current = dst->first;
15011debfc3dSmrg
15021debfc3dSmrg if (dst_elt)
15031debfc3dSmrg {
15041debfc3dSmrg changed = true;
15051debfc3dSmrg bitmap_elt_clear_from (dst, dst_elt);
15061debfc3dSmrg }
15071debfc3dSmrg gcc_checking_assert (!dst->current == !dst->first);
15081debfc3dSmrg if (dst->current)
15091debfc3dSmrg dst->indx = dst->current->indx;
15101debfc3dSmrg
15111debfc3dSmrg return changed;
15121debfc3dSmrg }
15131debfc3dSmrg
15141debfc3dSmrg /* A &= ~B. Returns true if A changes */
15151debfc3dSmrg
15161debfc3dSmrg bool
bitmap_and_compl_into(bitmap a,const_bitmap b)15171debfc3dSmrg bitmap_and_compl_into (bitmap a, const_bitmap b)
15181debfc3dSmrg {
15191debfc3dSmrg bitmap_element *a_elt = a->first;
15201debfc3dSmrg const bitmap_element *b_elt = b->first;
15211debfc3dSmrg bitmap_element *next;
15221debfc3dSmrg BITMAP_WORD changed = 0;
15231debfc3dSmrg
1524c0a68be4Smrg gcc_checking_assert (!a->tree_form && !b->tree_form);
1525c0a68be4Smrg
15261debfc3dSmrg if (a == b)
15271debfc3dSmrg {
15281debfc3dSmrg if (bitmap_empty_p (a))
15291debfc3dSmrg return false;
15301debfc3dSmrg else
15311debfc3dSmrg {
15321debfc3dSmrg bitmap_clear (a);
15331debfc3dSmrg return true;
15341debfc3dSmrg }
15351debfc3dSmrg }
15361debfc3dSmrg
15371debfc3dSmrg while (a_elt && b_elt)
15381debfc3dSmrg {
15391debfc3dSmrg if (a_elt->indx < b_elt->indx)
15401debfc3dSmrg a_elt = a_elt->next;
15411debfc3dSmrg else if (b_elt->indx < a_elt->indx)
15421debfc3dSmrg b_elt = b_elt->next;
15431debfc3dSmrg else
15441debfc3dSmrg {
15451debfc3dSmrg /* Matching elts, generate A &= ~B. */
15461debfc3dSmrg unsigned ix;
15471debfc3dSmrg BITMAP_WORD ior = 0;
15481debfc3dSmrg
15491debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
15501debfc3dSmrg {
15511debfc3dSmrg BITMAP_WORD cleared = a_elt->bits[ix] & b_elt->bits[ix];
15521debfc3dSmrg BITMAP_WORD r = a_elt->bits[ix] ^ cleared;
15531debfc3dSmrg
15541debfc3dSmrg a_elt->bits[ix] = r;
15551debfc3dSmrg changed |= cleared;
15561debfc3dSmrg ior |= r;
15571debfc3dSmrg }
15581debfc3dSmrg next = a_elt->next;
15591debfc3dSmrg if (!ior)
1560c0a68be4Smrg bitmap_list_unlink_element (a, a_elt);
15611debfc3dSmrg a_elt = next;
15621debfc3dSmrg b_elt = b_elt->next;
15631debfc3dSmrg }
15641debfc3dSmrg }
15651debfc3dSmrg gcc_checking_assert (!a->current == !a->first
15661debfc3dSmrg && (!a->current || a->indx == a->current->indx));
15671debfc3dSmrg return changed != 0;
15681debfc3dSmrg }
15691debfc3dSmrg
15701debfc3dSmrg /* Set COUNT bits from START in HEAD. */
15711debfc3dSmrg void
bitmap_set_range(bitmap head,unsigned int start,unsigned int count)15721debfc3dSmrg bitmap_set_range (bitmap head, unsigned int start, unsigned int count)
15731debfc3dSmrg {
15741debfc3dSmrg unsigned int first_index, end_bit_plus1, last_index;
15751debfc3dSmrg bitmap_element *elt, *elt_prev;
15761debfc3dSmrg unsigned int i;
15771debfc3dSmrg
1578c0a68be4Smrg gcc_checking_assert (!head->tree_form);
1579c0a68be4Smrg
15801debfc3dSmrg if (!count)
15811debfc3dSmrg return;
15821debfc3dSmrg
15831debfc3dSmrg if (count == 1)
15841debfc3dSmrg {
15851debfc3dSmrg bitmap_set_bit (head, start);
15861debfc3dSmrg return;
15871debfc3dSmrg }
15881debfc3dSmrg
15891debfc3dSmrg first_index = start / BITMAP_ELEMENT_ALL_BITS;
15901debfc3dSmrg end_bit_plus1 = start + count;
15911debfc3dSmrg last_index = (end_bit_plus1 - 1) / BITMAP_ELEMENT_ALL_BITS;
1592c0a68be4Smrg elt = bitmap_list_find_element (head, first_index);
15931debfc3dSmrg
1594c0a68be4Smrg /* If bitmap_list_find_element returns zero, the current is the closest block
15951debfc3dSmrg to the result. Otherwise, just use bitmap_element_allocate to
15961debfc3dSmrg ensure ELT is set; in the loop below, ELT == NULL means "insert
15971debfc3dSmrg at the end of the bitmap". */
15981debfc3dSmrg if (!elt)
15991debfc3dSmrg {
16001debfc3dSmrg elt = bitmap_element_allocate (head);
16011debfc3dSmrg elt->indx = first_index;
1602c0a68be4Smrg bitmap_list_link_element (head, elt);
16031debfc3dSmrg }
16041debfc3dSmrg
16051debfc3dSmrg gcc_checking_assert (elt->indx == first_index);
16061debfc3dSmrg elt_prev = elt->prev;
16071debfc3dSmrg for (i = first_index; i <= last_index; i++)
16081debfc3dSmrg {
16091debfc3dSmrg unsigned elt_start_bit = i * BITMAP_ELEMENT_ALL_BITS;
16101debfc3dSmrg unsigned elt_end_bit_plus1 = elt_start_bit + BITMAP_ELEMENT_ALL_BITS;
16111debfc3dSmrg
16121debfc3dSmrg unsigned int first_word_to_mod;
16131debfc3dSmrg BITMAP_WORD first_mask;
16141debfc3dSmrg unsigned int last_word_to_mod;
16151debfc3dSmrg BITMAP_WORD last_mask;
16161debfc3dSmrg unsigned int ix;
16171debfc3dSmrg
16181debfc3dSmrg if (!elt || elt->indx != i)
1619c0a68be4Smrg elt = bitmap_list_insert_element_after (head, elt_prev, i);
16201debfc3dSmrg
16211debfc3dSmrg if (elt_start_bit <= start)
16221debfc3dSmrg {
16231debfc3dSmrg /* The first bit to turn on is somewhere inside this
16241debfc3dSmrg elt. */
16251debfc3dSmrg first_word_to_mod = (start - elt_start_bit) / BITMAP_WORD_BITS;
16261debfc3dSmrg
16271debfc3dSmrg /* This mask should have 1s in all bits >= start position. */
16281debfc3dSmrg first_mask =
16291debfc3dSmrg (((BITMAP_WORD) 1) << ((start % BITMAP_WORD_BITS))) - 1;
16301debfc3dSmrg first_mask = ~first_mask;
16311debfc3dSmrg }
16321debfc3dSmrg else
16331debfc3dSmrg {
16341debfc3dSmrg /* The first bit to turn on is below this start of this elt. */
16351debfc3dSmrg first_word_to_mod = 0;
16361debfc3dSmrg first_mask = ~(BITMAP_WORD) 0;
16371debfc3dSmrg }
16381debfc3dSmrg
16391debfc3dSmrg if (elt_end_bit_plus1 <= end_bit_plus1)
16401debfc3dSmrg {
16411debfc3dSmrg /* The last bit to turn on is beyond this elt. */
16421debfc3dSmrg last_word_to_mod = BITMAP_ELEMENT_WORDS - 1;
16431debfc3dSmrg last_mask = ~(BITMAP_WORD) 0;
16441debfc3dSmrg }
16451debfc3dSmrg else
16461debfc3dSmrg {
16471debfc3dSmrg /* The last bit to turn on is inside to this elt. */
16481debfc3dSmrg last_word_to_mod =
16491debfc3dSmrg (end_bit_plus1 - elt_start_bit) / BITMAP_WORD_BITS;
16501debfc3dSmrg
16511debfc3dSmrg /* The last mask should have 1s below the end bit. */
16521debfc3dSmrg last_mask =
16531debfc3dSmrg (((BITMAP_WORD) 1) << ((end_bit_plus1 % BITMAP_WORD_BITS))) - 1;
16541debfc3dSmrg }
16551debfc3dSmrg
16561debfc3dSmrg if (first_word_to_mod == last_word_to_mod)
16571debfc3dSmrg {
16581debfc3dSmrg BITMAP_WORD mask = first_mask & last_mask;
16591debfc3dSmrg elt->bits[first_word_to_mod] |= mask;
16601debfc3dSmrg }
16611debfc3dSmrg else
16621debfc3dSmrg {
16631debfc3dSmrg elt->bits[first_word_to_mod] |= first_mask;
16641debfc3dSmrg if (BITMAP_ELEMENT_WORDS > 2)
16651debfc3dSmrg for (ix = first_word_to_mod + 1; ix < last_word_to_mod; ix++)
16661debfc3dSmrg elt->bits[ix] = ~(BITMAP_WORD) 0;
16671debfc3dSmrg elt->bits[last_word_to_mod] |= last_mask;
16681debfc3dSmrg }
16691debfc3dSmrg
16701debfc3dSmrg elt_prev = elt;
16711debfc3dSmrg elt = elt->next;
16721debfc3dSmrg }
16731debfc3dSmrg
16741debfc3dSmrg head->current = elt ? elt : elt_prev;
16751debfc3dSmrg head->indx = head->current->indx;
16761debfc3dSmrg }
16771debfc3dSmrg
16781debfc3dSmrg /* Clear COUNT bits from START in HEAD. */
16791debfc3dSmrg void
bitmap_clear_range(bitmap head,unsigned int start,unsigned int count)16801debfc3dSmrg bitmap_clear_range (bitmap head, unsigned int start, unsigned int count)
16811debfc3dSmrg {
16821debfc3dSmrg unsigned int first_index, end_bit_plus1, last_index;
16831debfc3dSmrg bitmap_element *elt;
16841debfc3dSmrg
1685c0a68be4Smrg gcc_checking_assert (!head->tree_form);
1686c0a68be4Smrg
16871debfc3dSmrg if (!count)
16881debfc3dSmrg return;
16891debfc3dSmrg
16901debfc3dSmrg if (count == 1)
16911debfc3dSmrg {
16921debfc3dSmrg bitmap_clear_bit (head, start);
16931debfc3dSmrg return;
16941debfc3dSmrg }
16951debfc3dSmrg
16961debfc3dSmrg first_index = start / BITMAP_ELEMENT_ALL_BITS;
16971debfc3dSmrg end_bit_plus1 = start + count;
16981debfc3dSmrg last_index = (end_bit_plus1 - 1) / BITMAP_ELEMENT_ALL_BITS;
1699c0a68be4Smrg elt = bitmap_list_find_element (head, first_index);
17001debfc3dSmrg
1701c0a68be4Smrg /* If bitmap_list_find_element returns zero, the current is the closest block
17021debfc3dSmrg to the result. If the current is less than first index, find the
17031debfc3dSmrg next one. Otherwise, just set elt to be current. */
17041debfc3dSmrg if (!elt)
17051debfc3dSmrg {
17061debfc3dSmrg if (head->current)
17071debfc3dSmrg {
17081debfc3dSmrg if (head->indx < first_index)
17091debfc3dSmrg {
17101debfc3dSmrg elt = head->current->next;
17111debfc3dSmrg if (!elt)
17121debfc3dSmrg return;
17131debfc3dSmrg }
17141debfc3dSmrg else
17151debfc3dSmrg elt = head->current;
17161debfc3dSmrg }
17171debfc3dSmrg else
17181debfc3dSmrg return;
17191debfc3dSmrg }
17201debfc3dSmrg
17211debfc3dSmrg while (elt && (elt->indx <= last_index))
17221debfc3dSmrg {
17231debfc3dSmrg bitmap_element * next_elt = elt->next;
17241debfc3dSmrg unsigned elt_start_bit = (elt->indx) * BITMAP_ELEMENT_ALL_BITS;
17251debfc3dSmrg unsigned elt_end_bit_plus1 = elt_start_bit + BITMAP_ELEMENT_ALL_BITS;
17261debfc3dSmrg
17271debfc3dSmrg
17281debfc3dSmrg if (elt_start_bit >= start && elt_end_bit_plus1 <= end_bit_plus1)
17291debfc3dSmrg /* Get rid of the entire elt and go to the next one. */
1730c0a68be4Smrg bitmap_list_unlink_element (head, elt);
17311debfc3dSmrg else
17321debfc3dSmrg {
17331debfc3dSmrg /* Going to have to knock out some bits in this elt. */
17341debfc3dSmrg unsigned int first_word_to_mod;
17351debfc3dSmrg BITMAP_WORD first_mask;
17361debfc3dSmrg unsigned int last_word_to_mod;
17371debfc3dSmrg BITMAP_WORD last_mask;
17381debfc3dSmrg unsigned int i;
17391debfc3dSmrg bool clear = true;
17401debfc3dSmrg
17411debfc3dSmrg if (elt_start_bit <= start)
17421debfc3dSmrg {
17431debfc3dSmrg /* The first bit to turn off is somewhere inside this
17441debfc3dSmrg elt. */
17451debfc3dSmrg first_word_to_mod = (start - elt_start_bit) / BITMAP_WORD_BITS;
17461debfc3dSmrg
17471debfc3dSmrg /* This mask should have 1s in all bits >= start position. */
17481debfc3dSmrg first_mask =
17491debfc3dSmrg (((BITMAP_WORD) 1) << ((start % BITMAP_WORD_BITS))) - 1;
17501debfc3dSmrg first_mask = ~first_mask;
17511debfc3dSmrg }
17521debfc3dSmrg else
17531debfc3dSmrg {
17541debfc3dSmrg /* The first bit to turn off is below this start of this elt. */
17551debfc3dSmrg first_word_to_mod = 0;
17561debfc3dSmrg first_mask = 0;
17571debfc3dSmrg first_mask = ~first_mask;
17581debfc3dSmrg }
17591debfc3dSmrg
17601debfc3dSmrg if (elt_end_bit_plus1 <= end_bit_plus1)
17611debfc3dSmrg {
17621debfc3dSmrg /* The last bit to turn off is beyond this elt. */
17631debfc3dSmrg last_word_to_mod = BITMAP_ELEMENT_WORDS - 1;
17641debfc3dSmrg last_mask = 0;
17651debfc3dSmrg last_mask = ~last_mask;
17661debfc3dSmrg }
17671debfc3dSmrg else
17681debfc3dSmrg {
17691debfc3dSmrg /* The last bit to turn off is inside to this elt. */
17701debfc3dSmrg last_word_to_mod =
17711debfc3dSmrg (end_bit_plus1 - elt_start_bit) / BITMAP_WORD_BITS;
17721debfc3dSmrg
17731debfc3dSmrg /* The last mask should have 1s below the end bit. */
17741debfc3dSmrg last_mask =
17751debfc3dSmrg (((BITMAP_WORD) 1) << (((end_bit_plus1) % BITMAP_WORD_BITS))) - 1;
17761debfc3dSmrg }
17771debfc3dSmrg
17781debfc3dSmrg
17791debfc3dSmrg if (first_word_to_mod == last_word_to_mod)
17801debfc3dSmrg {
17811debfc3dSmrg BITMAP_WORD mask = first_mask & last_mask;
17821debfc3dSmrg elt->bits[first_word_to_mod] &= ~mask;
17831debfc3dSmrg }
17841debfc3dSmrg else
17851debfc3dSmrg {
17861debfc3dSmrg elt->bits[first_word_to_mod] &= ~first_mask;
17871debfc3dSmrg if (BITMAP_ELEMENT_WORDS > 2)
17881debfc3dSmrg for (i = first_word_to_mod + 1; i < last_word_to_mod; i++)
17891debfc3dSmrg elt->bits[i] = 0;
17901debfc3dSmrg elt->bits[last_word_to_mod] &= ~last_mask;
17911debfc3dSmrg }
17921debfc3dSmrg for (i = 0; i < BITMAP_ELEMENT_WORDS; i++)
17931debfc3dSmrg if (elt->bits[i])
17941debfc3dSmrg {
17951debfc3dSmrg clear = false;
17961debfc3dSmrg break;
17971debfc3dSmrg }
17981debfc3dSmrg /* Check to see if there are any bits left. */
17991debfc3dSmrg if (clear)
1800c0a68be4Smrg bitmap_list_unlink_element (head, elt);
18011debfc3dSmrg }
18021debfc3dSmrg elt = next_elt;
18031debfc3dSmrg }
18041debfc3dSmrg
18051debfc3dSmrg if (elt)
18061debfc3dSmrg {
18071debfc3dSmrg head->current = elt;
18081debfc3dSmrg head->indx = head->current->indx;
18091debfc3dSmrg }
18101debfc3dSmrg }
18111debfc3dSmrg
18121debfc3dSmrg /* A = ~A & B. */
18131debfc3dSmrg
18141debfc3dSmrg void
bitmap_compl_and_into(bitmap a,const_bitmap b)18151debfc3dSmrg bitmap_compl_and_into (bitmap a, const_bitmap b)
18161debfc3dSmrg {
18171debfc3dSmrg bitmap_element *a_elt = a->first;
18181debfc3dSmrg const bitmap_element *b_elt = b->first;
18191debfc3dSmrg bitmap_element *a_prev = NULL;
18201debfc3dSmrg bitmap_element *next;
18211debfc3dSmrg
1822c0a68be4Smrg gcc_checking_assert (!a->tree_form && !b->tree_form);
18231debfc3dSmrg gcc_assert (a != b);
18241debfc3dSmrg
18251debfc3dSmrg if (bitmap_empty_p (a))
18261debfc3dSmrg {
18271debfc3dSmrg bitmap_copy (a, b);
18281debfc3dSmrg return;
18291debfc3dSmrg }
18301debfc3dSmrg if (bitmap_empty_p (b))
18311debfc3dSmrg {
18321debfc3dSmrg bitmap_clear (a);
18331debfc3dSmrg return;
18341debfc3dSmrg }
18351debfc3dSmrg
18361debfc3dSmrg while (a_elt || b_elt)
18371debfc3dSmrg {
18381debfc3dSmrg if (!b_elt || (a_elt && a_elt->indx < b_elt->indx))
18391debfc3dSmrg {
18401debfc3dSmrg /* A is before B. Remove A */
18411debfc3dSmrg next = a_elt->next;
18421debfc3dSmrg a_prev = a_elt->prev;
1843c0a68be4Smrg bitmap_list_unlink_element (a, a_elt);
18441debfc3dSmrg a_elt = next;
18451debfc3dSmrg }
18461debfc3dSmrg else if (!a_elt || b_elt->indx < a_elt->indx)
18471debfc3dSmrg {
18481debfc3dSmrg /* B is before A. Copy B. */
1849c0a68be4Smrg next = bitmap_list_insert_element_after (a, a_prev, b_elt->indx);
18501debfc3dSmrg memcpy (next->bits, b_elt->bits, sizeof (next->bits));
18511debfc3dSmrg a_prev = next;
18521debfc3dSmrg b_elt = b_elt->next;
18531debfc3dSmrg }
18541debfc3dSmrg else
18551debfc3dSmrg {
18561debfc3dSmrg /* Matching elts, generate A = ~A & B. */
18571debfc3dSmrg unsigned ix;
18581debfc3dSmrg BITMAP_WORD ior = 0;
18591debfc3dSmrg
18601debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
18611debfc3dSmrg {
18621debfc3dSmrg BITMAP_WORD cleared = a_elt->bits[ix] & b_elt->bits[ix];
18631debfc3dSmrg BITMAP_WORD r = b_elt->bits[ix] ^ cleared;
18641debfc3dSmrg
18651debfc3dSmrg a_elt->bits[ix] = r;
18661debfc3dSmrg ior |= r;
18671debfc3dSmrg }
18681debfc3dSmrg next = a_elt->next;
18691debfc3dSmrg if (!ior)
1870c0a68be4Smrg bitmap_list_unlink_element (a, a_elt);
18711debfc3dSmrg else
18721debfc3dSmrg a_prev = a_elt;
18731debfc3dSmrg a_elt = next;
18741debfc3dSmrg b_elt = b_elt->next;
18751debfc3dSmrg }
18761debfc3dSmrg }
18771debfc3dSmrg gcc_checking_assert (!a->current == !a->first
18781debfc3dSmrg && (!a->current || a->indx == a->current->indx));
18791debfc3dSmrg return;
18801debfc3dSmrg }
18811debfc3dSmrg
18821debfc3dSmrg
18831debfc3dSmrg /* Insert an element corresponding to A_ELT | B_ELT after DST_PREV,
18841debfc3dSmrg overwriting DST_ELT if non-NULL. CHANGED is true if the destination bitmap
18851debfc3dSmrg had already been changed; the new value of CHANGED is returned. */
18861debfc3dSmrg
18871debfc3dSmrg static inline bool
bitmap_elt_ior(bitmap dst,bitmap_element * dst_elt,bitmap_element * dst_prev,const bitmap_element * a_elt,const bitmap_element * b_elt,bool changed)18881debfc3dSmrg bitmap_elt_ior (bitmap dst, bitmap_element *dst_elt, bitmap_element *dst_prev,
18891debfc3dSmrg const bitmap_element *a_elt, const bitmap_element *b_elt,
18901debfc3dSmrg bool changed)
18911debfc3dSmrg {
18921debfc3dSmrg gcc_assert (a_elt || b_elt);
18931debfc3dSmrg
18941debfc3dSmrg if (a_elt && b_elt && a_elt->indx == b_elt->indx)
18951debfc3dSmrg {
18961debfc3dSmrg /* Matching elts, generate A | B. */
18971debfc3dSmrg unsigned ix;
18981debfc3dSmrg
18991debfc3dSmrg if (!changed && dst_elt && dst_elt->indx == a_elt->indx)
19001debfc3dSmrg {
19011debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
19021debfc3dSmrg {
19031debfc3dSmrg BITMAP_WORD r = a_elt->bits[ix] | b_elt->bits[ix];
19041debfc3dSmrg if (r != dst_elt->bits[ix])
19051debfc3dSmrg {
19061debfc3dSmrg dst_elt->bits[ix] = r;
19071debfc3dSmrg changed = true;
19081debfc3dSmrg }
19091debfc3dSmrg }
19101debfc3dSmrg }
19111debfc3dSmrg else
19121debfc3dSmrg {
19131debfc3dSmrg changed = true;
19141debfc3dSmrg if (!dst_elt)
1915c0a68be4Smrg dst_elt = bitmap_list_insert_element_after (dst, dst_prev,
1916c0a68be4Smrg a_elt->indx);
19171debfc3dSmrg else
19181debfc3dSmrg dst_elt->indx = a_elt->indx;
19191debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
19201debfc3dSmrg {
19211debfc3dSmrg BITMAP_WORD r = a_elt->bits[ix] | b_elt->bits[ix];
19221debfc3dSmrg dst_elt->bits[ix] = r;
19231debfc3dSmrg }
19241debfc3dSmrg }
19251debfc3dSmrg }
19261debfc3dSmrg else
19271debfc3dSmrg {
19281debfc3dSmrg /* Copy a single element. */
19291debfc3dSmrg const bitmap_element *src;
19301debfc3dSmrg
19311debfc3dSmrg if (!b_elt || (a_elt && a_elt->indx < b_elt->indx))
19321debfc3dSmrg src = a_elt;
19331debfc3dSmrg else
19341debfc3dSmrg src = b_elt;
19351debfc3dSmrg
19361debfc3dSmrg gcc_checking_assert (src);
19371debfc3dSmrg changed = bitmap_elt_copy (dst, dst_elt, dst_prev, src, changed);
19381debfc3dSmrg }
19391debfc3dSmrg return changed;
19401debfc3dSmrg }
19411debfc3dSmrg
19421debfc3dSmrg
19431debfc3dSmrg /* DST = A | B. Return true if DST changes. */
19441debfc3dSmrg
19451debfc3dSmrg bool
bitmap_ior(bitmap dst,const_bitmap a,const_bitmap b)19461debfc3dSmrg bitmap_ior (bitmap dst, const_bitmap a, const_bitmap b)
19471debfc3dSmrg {
19481debfc3dSmrg bitmap_element *dst_elt = dst->first;
19491debfc3dSmrg const bitmap_element *a_elt = a->first;
19501debfc3dSmrg const bitmap_element *b_elt = b->first;
19511debfc3dSmrg bitmap_element *dst_prev = NULL;
19521debfc3dSmrg bitmap_element **dst_prev_pnext = &dst->first;
19531debfc3dSmrg bool changed = false;
19541debfc3dSmrg
1955c0a68be4Smrg gcc_checking_assert (!dst->tree_form && !a->tree_form && !b->tree_form);
19561debfc3dSmrg gcc_assert (dst != a && dst != b);
19571debfc3dSmrg
19581debfc3dSmrg while (a_elt || b_elt)
19591debfc3dSmrg {
19601debfc3dSmrg changed = bitmap_elt_ior (dst, dst_elt, dst_prev, a_elt, b_elt, changed);
19611debfc3dSmrg
19621debfc3dSmrg if (a_elt && b_elt && a_elt->indx == b_elt->indx)
19631debfc3dSmrg {
19641debfc3dSmrg a_elt = a_elt->next;
19651debfc3dSmrg b_elt = b_elt->next;
19661debfc3dSmrg }
19671debfc3dSmrg else
19681debfc3dSmrg {
19691debfc3dSmrg if (a_elt && (!b_elt || a_elt->indx <= b_elt->indx))
19701debfc3dSmrg a_elt = a_elt->next;
19711debfc3dSmrg else if (b_elt && (!a_elt || b_elt->indx <= a_elt->indx))
19721debfc3dSmrg b_elt = b_elt->next;
19731debfc3dSmrg }
19741debfc3dSmrg
19751debfc3dSmrg dst_prev = *dst_prev_pnext;
19761debfc3dSmrg dst_prev_pnext = &dst_prev->next;
19771debfc3dSmrg dst_elt = *dst_prev_pnext;
19781debfc3dSmrg }
19791debfc3dSmrg
19801debfc3dSmrg if (dst_elt)
19811debfc3dSmrg {
19821debfc3dSmrg changed = true;
19831debfc3dSmrg /* Ensure that dst->current is valid. */
19841debfc3dSmrg dst->current = dst->first;
19851debfc3dSmrg bitmap_elt_clear_from (dst, dst_elt);
19861debfc3dSmrg }
19871debfc3dSmrg gcc_checking_assert (!dst->current == !dst->first);
19881debfc3dSmrg if (dst->current)
19891debfc3dSmrg dst->indx = dst->current->indx;
19901debfc3dSmrg return changed;
19911debfc3dSmrg }
19921debfc3dSmrg
19931debfc3dSmrg /* A |= B. Return true if A changes. */
19941debfc3dSmrg
19951debfc3dSmrg bool
bitmap_ior_into(bitmap a,const_bitmap b)19961debfc3dSmrg bitmap_ior_into (bitmap a, const_bitmap b)
19971debfc3dSmrg {
19981debfc3dSmrg bitmap_element *a_elt = a->first;
19991debfc3dSmrg const bitmap_element *b_elt = b->first;
20001debfc3dSmrg bitmap_element *a_prev = NULL;
20011debfc3dSmrg bitmap_element **a_prev_pnext = &a->first;
20021debfc3dSmrg bool changed = false;
20031debfc3dSmrg
2004c0a68be4Smrg gcc_checking_assert (!a->tree_form && !b->tree_form);
20051debfc3dSmrg if (a == b)
20061debfc3dSmrg return false;
20071debfc3dSmrg
20081debfc3dSmrg while (b_elt)
20091debfc3dSmrg {
20101debfc3dSmrg /* If A lags behind B, just advance it. */
20111debfc3dSmrg if (!a_elt || a_elt->indx == b_elt->indx)
20121debfc3dSmrg {
20131debfc3dSmrg changed = bitmap_elt_ior (a, a_elt, a_prev, a_elt, b_elt, changed);
20141debfc3dSmrg b_elt = b_elt->next;
20151debfc3dSmrg }
20161debfc3dSmrg else if (a_elt->indx > b_elt->indx)
20171debfc3dSmrg {
20181debfc3dSmrg changed = bitmap_elt_copy (a, NULL, a_prev, b_elt, changed);
20191debfc3dSmrg b_elt = b_elt->next;
20201debfc3dSmrg }
20211debfc3dSmrg
20221debfc3dSmrg a_prev = *a_prev_pnext;
20231debfc3dSmrg a_prev_pnext = &a_prev->next;
20241debfc3dSmrg a_elt = *a_prev_pnext;
20251debfc3dSmrg }
20261debfc3dSmrg
20271debfc3dSmrg gcc_checking_assert (!a->current == !a->first);
20281debfc3dSmrg if (a->current)
20291debfc3dSmrg a->indx = a->current->indx;
20301debfc3dSmrg return changed;
20311debfc3dSmrg }
20321debfc3dSmrg
2033*8feb0f0bSmrg /* A |= B. Return true if A changes. Free B (re-using its storage
2034*8feb0f0bSmrg for the result). */
2035*8feb0f0bSmrg
2036*8feb0f0bSmrg bool
bitmap_ior_into_and_free(bitmap a,bitmap * b_)2037*8feb0f0bSmrg bitmap_ior_into_and_free (bitmap a, bitmap *b_)
2038*8feb0f0bSmrg {
2039*8feb0f0bSmrg bitmap b = *b_;
2040*8feb0f0bSmrg bitmap_element *a_elt = a->first;
2041*8feb0f0bSmrg bitmap_element *b_elt = b->first;
2042*8feb0f0bSmrg bitmap_element *a_prev = NULL;
2043*8feb0f0bSmrg bitmap_element **a_prev_pnext = &a->first;
2044*8feb0f0bSmrg bool changed = false;
2045*8feb0f0bSmrg
2046*8feb0f0bSmrg gcc_checking_assert (!a->tree_form && !b->tree_form);
2047*8feb0f0bSmrg gcc_assert (a->obstack == b->obstack);
2048*8feb0f0bSmrg if (a == b)
2049*8feb0f0bSmrg return false;
2050*8feb0f0bSmrg
2051*8feb0f0bSmrg while (b_elt)
2052*8feb0f0bSmrg {
2053*8feb0f0bSmrg /* If A lags behind B, just advance it. */
2054*8feb0f0bSmrg if (!a_elt || a_elt->indx == b_elt->indx)
2055*8feb0f0bSmrg {
2056*8feb0f0bSmrg changed = bitmap_elt_ior (a, a_elt, a_prev, a_elt, b_elt, changed);
2057*8feb0f0bSmrg b_elt = b_elt->next;
2058*8feb0f0bSmrg }
2059*8feb0f0bSmrg else if (a_elt->indx > b_elt->indx)
2060*8feb0f0bSmrg {
2061*8feb0f0bSmrg bitmap_element *b_elt_next = b_elt->next;
2062*8feb0f0bSmrg bitmap_list_unlink_element (b, b_elt, false);
2063*8feb0f0bSmrg bitmap_list_insert_element_after (a, a_prev, b_elt->indx, b_elt);
2064*8feb0f0bSmrg b_elt = b_elt_next;
2065*8feb0f0bSmrg }
2066*8feb0f0bSmrg
2067*8feb0f0bSmrg a_prev = *a_prev_pnext;
2068*8feb0f0bSmrg a_prev_pnext = &a_prev->next;
2069*8feb0f0bSmrg a_elt = *a_prev_pnext;
2070*8feb0f0bSmrg }
2071*8feb0f0bSmrg
2072*8feb0f0bSmrg gcc_checking_assert (!a->current == !a->first);
2073*8feb0f0bSmrg if (a->current)
2074*8feb0f0bSmrg a->indx = a->current->indx;
2075*8feb0f0bSmrg
2076*8feb0f0bSmrg if (b->obstack)
2077*8feb0f0bSmrg BITMAP_FREE (*b_);
2078*8feb0f0bSmrg else
2079*8feb0f0bSmrg bitmap_clear (b);
2080*8feb0f0bSmrg return changed;
2081*8feb0f0bSmrg }
2082*8feb0f0bSmrg
20831debfc3dSmrg /* DST = A ^ B */
20841debfc3dSmrg
20851debfc3dSmrg void
bitmap_xor(bitmap dst,const_bitmap a,const_bitmap b)20861debfc3dSmrg bitmap_xor (bitmap dst, const_bitmap a, const_bitmap b)
20871debfc3dSmrg {
20881debfc3dSmrg bitmap_element *dst_elt = dst->first;
20891debfc3dSmrg const bitmap_element *a_elt = a->first;
20901debfc3dSmrg const bitmap_element *b_elt = b->first;
20911debfc3dSmrg bitmap_element *dst_prev = NULL;
20921debfc3dSmrg
2093c0a68be4Smrg gcc_checking_assert (!dst->tree_form && !a->tree_form && !b->tree_form);
20941debfc3dSmrg gcc_assert (dst != a && dst != b);
2095c0a68be4Smrg
20961debfc3dSmrg if (a == b)
20971debfc3dSmrg {
20981debfc3dSmrg bitmap_clear (dst);
20991debfc3dSmrg return;
21001debfc3dSmrg }
21011debfc3dSmrg
21021debfc3dSmrg while (a_elt || b_elt)
21031debfc3dSmrg {
21041debfc3dSmrg if (a_elt && b_elt && a_elt->indx == b_elt->indx)
21051debfc3dSmrg {
21061debfc3dSmrg /* Matching elts, generate A ^ B. */
21071debfc3dSmrg unsigned ix;
21081debfc3dSmrg BITMAP_WORD ior = 0;
21091debfc3dSmrg
21101debfc3dSmrg if (!dst_elt)
2111c0a68be4Smrg dst_elt = bitmap_list_insert_element_after (dst, dst_prev,
2112c0a68be4Smrg a_elt->indx);
21131debfc3dSmrg else
21141debfc3dSmrg dst_elt->indx = a_elt->indx;
21151debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
21161debfc3dSmrg {
21171debfc3dSmrg BITMAP_WORD r = a_elt->bits[ix] ^ b_elt->bits[ix];
21181debfc3dSmrg
21191debfc3dSmrg ior |= r;
21201debfc3dSmrg dst_elt->bits[ix] = r;
21211debfc3dSmrg }
21221debfc3dSmrg a_elt = a_elt->next;
21231debfc3dSmrg b_elt = b_elt->next;
21241debfc3dSmrg if (ior)
21251debfc3dSmrg {
21261debfc3dSmrg dst_prev = dst_elt;
21271debfc3dSmrg dst_elt = dst_elt->next;
21281debfc3dSmrg }
21291debfc3dSmrg }
21301debfc3dSmrg else
21311debfc3dSmrg {
21321debfc3dSmrg /* Copy a single element. */
21331debfc3dSmrg const bitmap_element *src;
21341debfc3dSmrg
21351debfc3dSmrg if (!b_elt || (a_elt && a_elt->indx < b_elt->indx))
21361debfc3dSmrg {
21371debfc3dSmrg src = a_elt;
21381debfc3dSmrg a_elt = a_elt->next;
21391debfc3dSmrg }
21401debfc3dSmrg else
21411debfc3dSmrg {
21421debfc3dSmrg src = b_elt;
21431debfc3dSmrg b_elt = b_elt->next;
21441debfc3dSmrg }
21451debfc3dSmrg
21461debfc3dSmrg if (!dst_elt)
2147c0a68be4Smrg dst_elt = bitmap_list_insert_element_after (dst, dst_prev,
2148c0a68be4Smrg src->indx);
21491debfc3dSmrg else
21501debfc3dSmrg dst_elt->indx = src->indx;
21511debfc3dSmrg memcpy (dst_elt->bits, src->bits, sizeof (dst_elt->bits));
21521debfc3dSmrg dst_prev = dst_elt;
21531debfc3dSmrg dst_elt = dst_elt->next;
21541debfc3dSmrg }
21551debfc3dSmrg }
21561debfc3dSmrg /* Ensure that dst->current is valid. */
21571debfc3dSmrg dst->current = dst->first;
21581debfc3dSmrg bitmap_elt_clear_from (dst, dst_elt);
21591debfc3dSmrg gcc_checking_assert (!dst->current == !dst->first);
21601debfc3dSmrg if (dst->current)
21611debfc3dSmrg dst->indx = dst->current->indx;
21621debfc3dSmrg }
21631debfc3dSmrg
21641debfc3dSmrg /* A ^= B */
21651debfc3dSmrg
21661debfc3dSmrg void
bitmap_xor_into(bitmap a,const_bitmap b)21671debfc3dSmrg bitmap_xor_into (bitmap a, const_bitmap b)
21681debfc3dSmrg {
21691debfc3dSmrg bitmap_element *a_elt = a->first;
21701debfc3dSmrg const bitmap_element *b_elt = b->first;
21711debfc3dSmrg bitmap_element *a_prev = NULL;
21721debfc3dSmrg
2173c0a68be4Smrg gcc_checking_assert (!a->tree_form && !b->tree_form);
2174c0a68be4Smrg
21751debfc3dSmrg if (a == b)
21761debfc3dSmrg {
21771debfc3dSmrg bitmap_clear (a);
21781debfc3dSmrg return;
21791debfc3dSmrg }
21801debfc3dSmrg
21811debfc3dSmrg while (b_elt)
21821debfc3dSmrg {
21831debfc3dSmrg if (!a_elt || b_elt->indx < a_elt->indx)
21841debfc3dSmrg {
21851debfc3dSmrg /* Copy b_elt. */
2186c0a68be4Smrg bitmap_element *dst = bitmap_list_insert_element_after (a, a_prev,
2187c0a68be4Smrg b_elt->indx);
21881debfc3dSmrg memcpy (dst->bits, b_elt->bits, sizeof (dst->bits));
21891debfc3dSmrg a_prev = dst;
21901debfc3dSmrg b_elt = b_elt->next;
21911debfc3dSmrg }
21921debfc3dSmrg else if (a_elt->indx < b_elt->indx)
21931debfc3dSmrg {
21941debfc3dSmrg a_prev = a_elt;
21951debfc3dSmrg a_elt = a_elt->next;
21961debfc3dSmrg }
21971debfc3dSmrg else
21981debfc3dSmrg {
21991debfc3dSmrg /* Matching elts, generate A ^= B. */
22001debfc3dSmrg unsigned ix;
22011debfc3dSmrg BITMAP_WORD ior = 0;
22021debfc3dSmrg bitmap_element *next = a_elt->next;
22031debfc3dSmrg
22041debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
22051debfc3dSmrg {
22061debfc3dSmrg BITMAP_WORD r = a_elt->bits[ix] ^ b_elt->bits[ix];
22071debfc3dSmrg
22081debfc3dSmrg ior |= r;
22091debfc3dSmrg a_elt->bits[ix] = r;
22101debfc3dSmrg }
22111debfc3dSmrg b_elt = b_elt->next;
22121debfc3dSmrg if (ior)
22131debfc3dSmrg a_prev = a_elt;
22141debfc3dSmrg else
2215c0a68be4Smrg bitmap_list_unlink_element (a, a_elt);
22161debfc3dSmrg a_elt = next;
22171debfc3dSmrg }
22181debfc3dSmrg }
22191debfc3dSmrg gcc_checking_assert (!a->current == !a->first);
22201debfc3dSmrg if (a->current)
22211debfc3dSmrg a->indx = a->current->indx;
22221debfc3dSmrg }
22231debfc3dSmrg
22241debfc3dSmrg /* Return true if two bitmaps are identical.
22251debfc3dSmrg We do not bother with a check for pointer equality, as that never
22261debfc3dSmrg occurs in practice. */
22271debfc3dSmrg
22281debfc3dSmrg bool
bitmap_equal_p(const_bitmap a,const_bitmap b)22291debfc3dSmrg bitmap_equal_p (const_bitmap a, const_bitmap b)
22301debfc3dSmrg {
22311debfc3dSmrg const bitmap_element *a_elt;
22321debfc3dSmrg const bitmap_element *b_elt;
22331debfc3dSmrg unsigned ix;
22341debfc3dSmrg
2235c0a68be4Smrg gcc_checking_assert (!a->tree_form && !b->tree_form);
2236c0a68be4Smrg
22371debfc3dSmrg for (a_elt = a->first, b_elt = b->first;
22381debfc3dSmrg a_elt && b_elt;
22391debfc3dSmrg a_elt = a_elt->next, b_elt = b_elt->next)
22401debfc3dSmrg {
22411debfc3dSmrg if (a_elt->indx != b_elt->indx)
22421debfc3dSmrg return false;
22431debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
22441debfc3dSmrg if (a_elt->bits[ix] != b_elt->bits[ix])
22451debfc3dSmrg return false;
22461debfc3dSmrg }
22471debfc3dSmrg return !a_elt && !b_elt;
22481debfc3dSmrg }
22491debfc3dSmrg
22501debfc3dSmrg /* Return true if A AND B is not empty. */
22511debfc3dSmrg
22521debfc3dSmrg bool
bitmap_intersect_p(const_bitmap a,const_bitmap b)22531debfc3dSmrg bitmap_intersect_p (const_bitmap a, const_bitmap b)
22541debfc3dSmrg {
22551debfc3dSmrg const bitmap_element *a_elt;
22561debfc3dSmrg const bitmap_element *b_elt;
22571debfc3dSmrg unsigned ix;
22581debfc3dSmrg
2259c0a68be4Smrg gcc_checking_assert (!a->tree_form && !b->tree_form);
2260c0a68be4Smrg
22611debfc3dSmrg for (a_elt = a->first, b_elt = b->first;
22621debfc3dSmrg a_elt && b_elt;)
22631debfc3dSmrg {
22641debfc3dSmrg if (a_elt->indx < b_elt->indx)
22651debfc3dSmrg a_elt = a_elt->next;
22661debfc3dSmrg else if (b_elt->indx < a_elt->indx)
22671debfc3dSmrg b_elt = b_elt->next;
22681debfc3dSmrg else
22691debfc3dSmrg {
22701debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
22711debfc3dSmrg if (a_elt->bits[ix] & b_elt->bits[ix])
22721debfc3dSmrg return true;
22731debfc3dSmrg a_elt = a_elt->next;
22741debfc3dSmrg b_elt = b_elt->next;
22751debfc3dSmrg }
22761debfc3dSmrg }
22771debfc3dSmrg return false;
22781debfc3dSmrg }
22791debfc3dSmrg
22801debfc3dSmrg /* Return true if A AND NOT B is not empty. */
22811debfc3dSmrg
22821debfc3dSmrg bool
bitmap_intersect_compl_p(const_bitmap a,const_bitmap b)22831debfc3dSmrg bitmap_intersect_compl_p (const_bitmap a, const_bitmap b)
22841debfc3dSmrg {
22851debfc3dSmrg const bitmap_element *a_elt;
22861debfc3dSmrg const bitmap_element *b_elt;
22871debfc3dSmrg unsigned ix;
2288c0a68be4Smrg
2289c0a68be4Smrg gcc_checking_assert (!a->tree_form && !b->tree_form);
2290c0a68be4Smrg
22911debfc3dSmrg for (a_elt = a->first, b_elt = b->first;
22921debfc3dSmrg a_elt && b_elt;)
22931debfc3dSmrg {
22941debfc3dSmrg if (a_elt->indx < b_elt->indx)
22951debfc3dSmrg return true;
22961debfc3dSmrg else if (b_elt->indx < a_elt->indx)
22971debfc3dSmrg b_elt = b_elt->next;
22981debfc3dSmrg else
22991debfc3dSmrg {
23001debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
23011debfc3dSmrg if (a_elt->bits[ix] & ~b_elt->bits[ix])
23021debfc3dSmrg return true;
23031debfc3dSmrg a_elt = a_elt->next;
23041debfc3dSmrg b_elt = b_elt->next;
23051debfc3dSmrg }
23061debfc3dSmrg }
23071debfc3dSmrg return a_elt != NULL;
23081debfc3dSmrg }
23091debfc3dSmrg
23101debfc3dSmrg
23111debfc3dSmrg /* DST = A | (FROM1 & ~FROM2). Return true if DST changes. */
23121debfc3dSmrg
23131debfc3dSmrg bool
bitmap_ior_and_compl(bitmap dst,const_bitmap a,const_bitmap b,const_bitmap kill)23141debfc3dSmrg bitmap_ior_and_compl (bitmap dst, const_bitmap a, const_bitmap b, const_bitmap kill)
23151debfc3dSmrg {
23161debfc3dSmrg bool changed = false;
23171debfc3dSmrg
23181debfc3dSmrg bitmap_element *dst_elt = dst->first;
23191debfc3dSmrg const bitmap_element *a_elt = a->first;
23201debfc3dSmrg const bitmap_element *b_elt = b->first;
23211debfc3dSmrg const bitmap_element *kill_elt = kill->first;
23221debfc3dSmrg bitmap_element *dst_prev = NULL;
23231debfc3dSmrg bitmap_element **dst_prev_pnext = &dst->first;
23241debfc3dSmrg
2325c0a68be4Smrg gcc_checking_assert (!dst->tree_form && !a->tree_form && !b->tree_form
2326c0a68be4Smrg && !kill->tree_form);
23271debfc3dSmrg gcc_assert (dst != a && dst != b && dst != kill);
23281debfc3dSmrg
23291debfc3dSmrg /* Special cases. We don't bother checking for bitmap_equal_p (b, kill). */
23301debfc3dSmrg if (b == kill || bitmap_empty_p (b))
23311debfc3dSmrg {
23321debfc3dSmrg changed = !bitmap_equal_p (dst, a);
23331debfc3dSmrg if (changed)
23341debfc3dSmrg bitmap_copy (dst, a);
23351debfc3dSmrg return changed;
23361debfc3dSmrg }
23371debfc3dSmrg if (bitmap_empty_p (kill))
23381debfc3dSmrg return bitmap_ior (dst, a, b);
23391debfc3dSmrg if (bitmap_empty_p (a))
23401debfc3dSmrg return bitmap_and_compl (dst, b, kill);
23411debfc3dSmrg
23421debfc3dSmrg while (a_elt || b_elt)
23431debfc3dSmrg {
23441debfc3dSmrg bool new_element = false;
23451debfc3dSmrg
23461debfc3dSmrg if (b_elt)
23471debfc3dSmrg while (kill_elt && kill_elt->indx < b_elt->indx)
23481debfc3dSmrg kill_elt = kill_elt->next;
23491debfc3dSmrg
23501debfc3dSmrg if (b_elt && kill_elt && kill_elt->indx == b_elt->indx
23511debfc3dSmrg && (!a_elt || a_elt->indx >= b_elt->indx))
23521debfc3dSmrg {
23531debfc3dSmrg bitmap_element tmp_elt;
23541debfc3dSmrg unsigned ix;
23551debfc3dSmrg
23561debfc3dSmrg BITMAP_WORD ior = 0;
23571debfc3dSmrg tmp_elt.indx = b_elt->indx;
23581debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
23591debfc3dSmrg {
23601debfc3dSmrg BITMAP_WORD r = b_elt->bits[ix] & ~kill_elt->bits[ix];
23611debfc3dSmrg ior |= r;
23621debfc3dSmrg tmp_elt.bits[ix] = r;
23631debfc3dSmrg }
23641debfc3dSmrg
23651debfc3dSmrg if (ior)
23661debfc3dSmrg {
23671debfc3dSmrg changed = bitmap_elt_ior (dst, dst_elt, dst_prev,
23681debfc3dSmrg a_elt, &tmp_elt, changed);
23691debfc3dSmrg new_element = true;
23701debfc3dSmrg if (a_elt && a_elt->indx == b_elt->indx)
23711debfc3dSmrg a_elt = a_elt->next;
23721debfc3dSmrg }
23731debfc3dSmrg
23741debfc3dSmrg b_elt = b_elt->next;
23751debfc3dSmrg kill_elt = kill_elt->next;
23761debfc3dSmrg }
23771debfc3dSmrg else
23781debfc3dSmrg {
23791debfc3dSmrg changed = bitmap_elt_ior (dst, dst_elt, dst_prev,
23801debfc3dSmrg a_elt, b_elt, changed);
23811debfc3dSmrg new_element = true;
23821debfc3dSmrg
23831debfc3dSmrg if (a_elt && b_elt && a_elt->indx == b_elt->indx)
23841debfc3dSmrg {
23851debfc3dSmrg a_elt = a_elt->next;
23861debfc3dSmrg b_elt = b_elt->next;
23871debfc3dSmrg }
23881debfc3dSmrg else
23891debfc3dSmrg {
23901debfc3dSmrg if (a_elt && (!b_elt || a_elt->indx <= b_elt->indx))
23911debfc3dSmrg a_elt = a_elt->next;
23921debfc3dSmrg else if (b_elt && (!a_elt || b_elt->indx <= a_elt->indx))
23931debfc3dSmrg b_elt = b_elt->next;
23941debfc3dSmrg }
23951debfc3dSmrg }
23961debfc3dSmrg
23971debfc3dSmrg if (new_element)
23981debfc3dSmrg {
23991debfc3dSmrg dst_prev = *dst_prev_pnext;
24001debfc3dSmrg dst_prev_pnext = &dst_prev->next;
24011debfc3dSmrg dst_elt = *dst_prev_pnext;
24021debfc3dSmrg }
24031debfc3dSmrg }
24041debfc3dSmrg
24051debfc3dSmrg if (dst_elt)
24061debfc3dSmrg {
24071debfc3dSmrg changed = true;
24081debfc3dSmrg /* Ensure that dst->current is valid. */
24091debfc3dSmrg dst->current = dst->first;
24101debfc3dSmrg bitmap_elt_clear_from (dst, dst_elt);
24111debfc3dSmrg }
24121debfc3dSmrg gcc_checking_assert (!dst->current == !dst->first);
24131debfc3dSmrg if (dst->current)
24141debfc3dSmrg dst->indx = dst->current->indx;
24151debfc3dSmrg
24161debfc3dSmrg return changed;
24171debfc3dSmrg }
24181debfc3dSmrg
2419c0a68be4Smrg /* A |= (B & ~C). Return true if A changes. */
24201debfc3dSmrg
24211debfc3dSmrg bool
bitmap_ior_and_compl_into(bitmap a,const_bitmap b,const_bitmap c)2422c0a68be4Smrg bitmap_ior_and_compl_into (bitmap a, const_bitmap b, const_bitmap c)
24231debfc3dSmrg {
2424*8feb0f0bSmrg bitmap_element *a_elt = a->first;
2425*8feb0f0bSmrg const bitmap_element *b_elt = b->first;
2426*8feb0f0bSmrg const bitmap_element *c_elt = c->first;
2427*8feb0f0bSmrg bitmap_element and_elt;
2428*8feb0f0bSmrg bitmap_element *a_prev = NULL;
2429*8feb0f0bSmrg bitmap_element **a_prev_pnext = &a->first;
2430*8feb0f0bSmrg bool changed = false;
2431*8feb0f0bSmrg unsigned ix;
24321debfc3dSmrg
2433c0a68be4Smrg gcc_checking_assert (!a->tree_form && !b->tree_form && !c->tree_form);
2434c0a68be4Smrg
2435*8feb0f0bSmrg if (a == b)
2436*8feb0f0bSmrg return false;
2437*8feb0f0bSmrg if (bitmap_empty_p (c))
2438*8feb0f0bSmrg return bitmap_ior_into (a, b);
2439*8feb0f0bSmrg else if (bitmap_empty_p (a))
2440*8feb0f0bSmrg return bitmap_and_compl (a, b, c);
24411debfc3dSmrg
2442*8feb0f0bSmrg and_elt.indx = -1;
2443*8feb0f0bSmrg while (b_elt)
2444*8feb0f0bSmrg {
2445*8feb0f0bSmrg /* Advance C. */
2446*8feb0f0bSmrg while (c_elt && c_elt->indx < b_elt->indx)
2447*8feb0f0bSmrg c_elt = c_elt->next;
2448*8feb0f0bSmrg
2449*8feb0f0bSmrg const bitmap_element *and_elt_ptr;
2450*8feb0f0bSmrg if (c_elt && c_elt->indx == b_elt->indx)
2451*8feb0f0bSmrg {
2452*8feb0f0bSmrg BITMAP_WORD overall = 0;
2453*8feb0f0bSmrg and_elt_ptr = &and_elt;
2454*8feb0f0bSmrg and_elt.indx = b_elt->indx;
2455*8feb0f0bSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
2456*8feb0f0bSmrg {
2457*8feb0f0bSmrg and_elt.bits[ix] = b_elt->bits[ix] & ~c_elt->bits[ix];
2458*8feb0f0bSmrg overall |= and_elt.bits[ix];
2459*8feb0f0bSmrg }
2460*8feb0f0bSmrg if (!overall)
2461*8feb0f0bSmrg {
2462*8feb0f0bSmrg b_elt = b_elt->next;
2463*8feb0f0bSmrg continue;
2464*8feb0f0bSmrg }
2465*8feb0f0bSmrg }
2466*8feb0f0bSmrg else
2467*8feb0f0bSmrg and_elt_ptr = b_elt;
2468*8feb0f0bSmrg
2469*8feb0f0bSmrg b_elt = b_elt->next;
2470*8feb0f0bSmrg
2471*8feb0f0bSmrg /* Now find a place to insert AND_ELT. */
2472*8feb0f0bSmrg do
2473*8feb0f0bSmrg {
2474*8feb0f0bSmrg ix = a_elt ? a_elt->indx : and_elt_ptr->indx;
2475*8feb0f0bSmrg if (ix == and_elt_ptr->indx)
2476*8feb0f0bSmrg changed = bitmap_elt_ior (a, a_elt, a_prev, a_elt,
2477*8feb0f0bSmrg and_elt_ptr, changed);
2478*8feb0f0bSmrg else if (ix > and_elt_ptr->indx)
2479*8feb0f0bSmrg changed = bitmap_elt_copy (a, NULL, a_prev, and_elt_ptr, changed);
2480*8feb0f0bSmrg
2481*8feb0f0bSmrg a_prev = *a_prev_pnext;
2482*8feb0f0bSmrg a_prev_pnext = &a_prev->next;
2483*8feb0f0bSmrg a_elt = *a_prev_pnext;
2484*8feb0f0bSmrg
2485*8feb0f0bSmrg /* If A lagged behind B/C, we advanced it so loop once more. */
2486*8feb0f0bSmrg }
2487*8feb0f0bSmrg while (ix < and_elt_ptr->indx);
2488*8feb0f0bSmrg }
2489*8feb0f0bSmrg
2490*8feb0f0bSmrg gcc_checking_assert (!a->current == !a->first);
2491*8feb0f0bSmrg if (a->current)
2492*8feb0f0bSmrg a->indx = a->current->indx;
24931debfc3dSmrg return changed;
24941debfc3dSmrg }
24951debfc3dSmrg
24961debfc3dSmrg /* A |= (B & C). Return true if A changes. */
24971debfc3dSmrg
24981debfc3dSmrg bool
bitmap_ior_and_into(bitmap a,const_bitmap b,const_bitmap c)24991debfc3dSmrg bitmap_ior_and_into (bitmap a, const_bitmap b, const_bitmap c)
25001debfc3dSmrg {
25011debfc3dSmrg bitmap_element *a_elt = a->first;
25021debfc3dSmrg const bitmap_element *b_elt = b->first;
25031debfc3dSmrg const bitmap_element *c_elt = c->first;
25041debfc3dSmrg bitmap_element and_elt;
25051debfc3dSmrg bitmap_element *a_prev = NULL;
25061debfc3dSmrg bitmap_element **a_prev_pnext = &a->first;
25071debfc3dSmrg bool changed = false;
25081debfc3dSmrg unsigned ix;
25091debfc3dSmrg
2510c0a68be4Smrg gcc_checking_assert (!a->tree_form && !b->tree_form && !c->tree_form);
2511c0a68be4Smrg
25121debfc3dSmrg if (b == c)
25131debfc3dSmrg return bitmap_ior_into (a, b);
25141debfc3dSmrg if (bitmap_empty_p (b) || bitmap_empty_p (c))
25151debfc3dSmrg return false;
25161debfc3dSmrg
25171debfc3dSmrg and_elt.indx = -1;
25181debfc3dSmrg while (b_elt && c_elt)
25191debfc3dSmrg {
25201debfc3dSmrg BITMAP_WORD overall;
25211debfc3dSmrg
25221debfc3dSmrg /* Find a common item of B and C. */
25231debfc3dSmrg while (b_elt->indx != c_elt->indx)
25241debfc3dSmrg {
25251debfc3dSmrg if (b_elt->indx < c_elt->indx)
25261debfc3dSmrg {
25271debfc3dSmrg b_elt = b_elt->next;
25281debfc3dSmrg if (!b_elt)
25291debfc3dSmrg goto done;
25301debfc3dSmrg }
25311debfc3dSmrg else
25321debfc3dSmrg {
25331debfc3dSmrg c_elt = c_elt->next;
25341debfc3dSmrg if (!c_elt)
25351debfc3dSmrg goto done;
25361debfc3dSmrg }
25371debfc3dSmrg }
25381debfc3dSmrg
25391debfc3dSmrg overall = 0;
25401debfc3dSmrg and_elt.indx = b_elt->indx;
25411debfc3dSmrg for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
25421debfc3dSmrg {
25431debfc3dSmrg and_elt.bits[ix] = b_elt->bits[ix] & c_elt->bits[ix];
25441debfc3dSmrg overall |= and_elt.bits[ix];
25451debfc3dSmrg }
25461debfc3dSmrg
25471debfc3dSmrg b_elt = b_elt->next;
25481debfc3dSmrg c_elt = c_elt->next;
25491debfc3dSmrg if (!overall)
25501debfc3dSmrg continue;
25511debfc3dSmrg
25521debfc3dSmrg /* Now find a place to insert AND_ELT. */
25531debfc3dSmrg do
25541debfc3dSmrg {
25551debfc3dSmrg ix = a_elt ? a_elt->indx : and_elt.indx;
25561debfc3dSmrg if (ix == and_elt.indx)
25571debfc3dSmrg changed = bitmap_elt_ior (a, a_elt, a_prev, a_elt, &and_elt, changed);
25581debfc3dSmrg else if (ix > and_elt.indx)
25591debfc3dSmrg changed = bitmap_elt_copy (a, NULL, a_prev, &and_elt, changed);
25601debfc3dSmrg
25611debfc3dSmrg a_prev = *a_prev_pnext;
25621debfc3dSmrg a_prev_pnext = &a_prev->next;
25631debfc3dSmrg a_elt = *a_prev_pnext;
25641debfc3dSmrg
25651debfc3dSmrg /* If A lagged behind B/C, we advanced it so loop once more. */
25661debfc3dSmrg }
25671debfc3dSmrg while (ix < and_elt.indx);
25681debfc3dSmrg }
25691debfc3dSmrg
25701debfc3dSmrg done:
25711debfc3dSmrg gcc_checking_assert (!a->current == !a->first);
25721debfc3dSmrg if (a->current)
25731debfc3dSmrg a->indx = a->current->indx;
25741debfc3dSmrg return changed;
25751debfc3dSmrg }
25761debfc3dSmrg
25771debfc3dSmrg /* Compute hash of bitmap (for purposes of hashing). */
2578c0a68be4Smrg
25791debfc3dSmrg hashval_t
bitmap_hash(const_bitmap head)25801debfc3dSmrg bitmap_hash (const_bitmap head)
25811debfc3dSmrg {
25821debfc3dSmrg const bitmap_element *ptr;
25831debfc3dSmrg BITMAP_WORD hash = 0;
25841debfc3dSmrg int ix;
25851debfc3dSmrg
2586c0a68be4Smrg gcc_checking_assert (!head->tree_form);
2587c0a68be4Smrg
25881debfc3dSmrg for (ptr = head->first; ptr; ptr = ptr->next)
25891debfc3dSmrg {
25901debfc3dSmrg hash ^= ptr->indx;
25911debfc3dSmrg for (ix = 0; ix != BITMAP_ELEMENT_WORDS; ix++)
25921debfc3dSmrg hash ^= ptr->bits[ix];
25931debfc3dSmrg }
25941debfc3dSmrg return (hashval_t)hash;
25951debfc3dSmrg }
25961debfc3dSmrg
25971debfc3dSmrg
2598c0a68be4Smrg /* Function to obtain a vector of bitmap elements in bit order from
2599c0a68be4Smrg HEAD in tree view. */
2600c0a68be4Smrg
2601c0a68be4Smrg static void
bitmap_tree_to_vec(vec<bitmap_element * > & elts,const_bitmap head)2602c0a68be4Smrg bitmap_tree_to_vec (vec<bitmap_element *> &elts, const_bitmap head)
2603c0a68be4Smrg {
2604c0a68be4Smrg gcc_checking_assert (head->tree_form);
2605c0a68be4Smrg auto_vec<bitmap_element *, 32> stack;
2606c0a68be4Smrg bitmap_element *e = head->first;
2607c0a68be4Smrg while (true)
2608c0a68be4Smrg {
2609c0a68be4Smrg while (e != NULL)
2610c0a68be4Smrg {
2611c0a68be4Smrg stack.safe_push (e);
2612c0a68be4Smrg e = e->prev;
2613c0a68be4Smrg }
2614c0a68be4Smrg if (stack.is_empty ())
2615c0a68be4Smrg break;
2616c0a68be4Smrg
2617c0a68be4Smrg e = stack.pop ();
2618c0a68be4Smrg elts.safe_push (e);
2619c0a68be4Smrg e = e->next;
2620c0a68be4Smrg }
2621c0a68be4Smrg }
2622c0a68be4Smrg
2623c0a68be4Smrg /* Debugging function to print out the contents of a bitmap element. */
26241debfc3dSmrg
26251debfc3dSmrg DEBUG_FUNCTION void
debug_bitmap_elt_file(FILE * file,const bitmap_element * ptr)2626c0a68be4Smrg debug_bitmap_elt_file (FILE *file, const bitmap_element *ptr)
26271debfc3dSmrg {
26281debfc3dSmrg unsigned int i, j, col = 26;
26291debfc3dSmrg
26301debfc3dSmrg fprintf (file, "\t" HOST_PTR_PRINTF " next = " HOST_PTR_PRINTF
26311debfc3dSmrg " prev = " HOST_PTR_PRINTF " indx = %u\n\t\tbits = {",
26321debfc3dSmrg (const void*) ptr, (const void*) ptr->next,
26331debfc3dSmrg (const void*) ptr->prev, ptr->indx);
26341debfc3dSmrg
26351debfc3dSmrg for (i = 0; i < BITMAP_ELEMENT_WORDS; i++)
26361debfc3dSmrg for (j = 0; j < BITMAP_WORD_BITS; j++)
26371debfc3dSmrg if ((ptr->bits[i] >> j) & 1)
26381debfc3dSmrg {
26391debfc3dSmrg if (col > 70)
26401debfc3dSmrg {
26411debfc3dSmrg fprintf (file, "\n\t\t\t");
26421debfc3dSmrg col = 24;
26431debfc3dSmrg }
26441debfc3dSmrg
26451debfc3dSmrg fprintf (file, " %u", (ptr->indx * BITMAP_ELEMENT_ALL_BITS
26461debfc3dSmrg + i * BITMAP_WORD_BITS + j));
26471debfc3dSmrg col += 4;
26481debfc3dSmrg }
26491debfc3dSmrg
26501debfc3dSmrg fprintf (file, " }\n");
26511debfc3dSmrg }
2652c0a68be4Smrg
2653c0a68be4Smrg /* Debugging function to print out the contents of a bitmap. */
2654c0a68be4Smrg
2655c0a68be4Smrg DEBUG_FUNCTION void
debug_bitmap_file(FILE * file,const_bitmap head)2656c0a68be4Smrg debug_bitmap_file (FILE *file, const_bitmap head)
2657c0a68be4Smrg {
2658c0a68be4Smrg const bitmap_element *ptr;
2659c0a68be4Smrg
2660c0a68be4Smrg fprintf (file, "\nfirst = " HOST_PTR_PRINTF
2661c0a68be4Smrg " current = " HOST_PTR_PRINTF " indx = %u\n",
2662c0a68be4Smrg (void *) head->first, (void *) head->current, head->indx);
2663c0a68be4Smrg
2664c0a68be4Smrg if (head->tree_form)
2665c0a68be4Smrg {
2666c0a68be4Smrg auto_vec<bitmap_element *, 32> elts;
2667c0a68be4Smrg bitmap_tree_to_vec (elts, head);
2668c0a68be4Smrg for (unsigned i = 0; i < elts.length (); ++i)
2669c0a68be4Smrg debug_bitmap_elt_file (file, elts[i]);
2670c0a68be4Smrg }
2671c0a68be4Smrg else
2672c0a68be4Smrg for (ptr = head->first; ptr; ptr = ptr->next)
2673c0a68be4Smrg debug_bitmap_elt_file (file, ptr);
26741debfc3dSmrg }
26751debfc3dSmrg
26761debfc3dSmrg /* Function to be called from the debugger to print the contents
26771debfc3dSmrg of a bitmap. */
26781debfc3dSmrg
26791debfc3dSmrg DEBUG_FUNCTION void
debug_bitmap(const_bitmap head)26801debfc3dSmrg debug_bitmap (const_bitmap head)
26811debfc3dSmrg {
26821debfc3dSmrg debug_bitmap_file (stderr, head);
26831debfc3dSmrg }
26841debfc3dSmrg
26851debfc3dSmrg /* Function to print out the contents of a bitmap. Unlike debug_bitmap_file,
26861debfc3dSmrg it does not print anything but the bits. */
26871debfc3dSmrg
26881debfc3dSmrg DEBUG_FUNCTION void
bitmap_print(FILE * file,const_bitmap head,const char * prefix,const char * suffix)26891debfc3dSmrg bitmap_print (FILE *file, const_bitmap head, const char *prefix,
26901debfc3dSmrg const char *suffix)
26911debfc3dSmrg {
26921debfc3dSmrg const char *comma = "";
26931debfc3dSmrg unsigned i;
26941debfc3dSmrg
26951debfc3dSmrg fputs (prefix, file);
2696c0a68be4Smrg if (head->tree_form)
2697c0a68be4Smrg {
2698c0a68be4Smrg auto_vec<bitmap_element *, 32> elts;
2699c0a68be4Smrg bitmap_tree_to_vec (elts, head);
2700c0a68be4Smrg for (i = 0; i < elts.length (); ++i)
2701c0a68be4Smrg for (unsigned ix = 0; ix != BITMAP_ELEMENT_WORDS; ++ix)
2702c0a68be4Smrg {
2703c0a68be4Smrg BITMAP_WORD word = elts[i]->bits[ix];
2704c0a68be4Smrg for (unsigned bit = 0; bit != BITMAP_WORD_BITS; ++bit)
2705c0a68be4Smrg if (word & ((BITMAP_WORD)1 << bit))
2706c0a68be4Smrg {
2707c0a68be4Smrg fprintf (file, "%s%d", comma,
2708c0a68be4Smrg (bit + BITMAP_WORD_BITS * ix
2709c0a68be4Smrg + elts[i]->indx * BITMAP_ELEMENT_ALL_BITS));
2710c0a68be4Smrg comma = ", ";
2711c0a68be4Smrg }
2712c0a68be4Smrg }
2713c0a68be4Smrg }
2714c0a68be4Smrg else
2715c0a68be4Smrg {
2716c0a68be4Smrg bitmap_iterator bi;
27171debfc3dSmrg EXECUTE_IF_SET_IN_BITMAP (head, 0, i, bi)
27181debfc3dSmrg {
27191debfc3dSmrg fprintf (file, "%s%d", comma, i);
27201debfc3dSmrg comma = ", ";
27211debfc3dSmrg }
2722c0a68be4Smrg }
27231debfc3dSmrg fputs (suffix, file);
27241debfc3dSmrg }
27251debfc3dSmrg
27261debfc3dSmrg /* Output per-bitmap memory usage statistics. */
27271debfc3dSmrg void
dump_bitmap_statistics(void)27281debfc3dSmrg dump_bitmap_statistics (void)
27291debfc3dSmrg {
27301debfc3dSmrg if (!GATHER_STATISTICS)
27311debfc3dSmrg return;
27321debfc3dSmrg
27331debfc3dSmrg bitmap_mem_desc.dump (BITMAP_ORIGIN);
27341debfc3dSmrg }
27351debfc3dSmrg
27361debfc3dSmrg DEBUG_FUNCTION void
debug(const bitmap_head & ref)27371debfc3dSmrg debug (const bitmap_head &ref)
27381debfc3dSmrg {
27391debfc3dSmrg dump_bitmap (stderr, &ref);
27401debfc3dSmrg }
27411debfc3dSmrg
27421debfc3dSmrg DEBUG_FUNCTION void
debug(const bitmap_head * ptr)27431debfc3dSmrg debug (const bitmap_head *ptr)
27441debfc3dSmrg {
27451debfc3dSmrg if (ptr)
27461debfc3dSmrg debug (*ptr);
27471debfc3dSmrg else
27481debfc3dSmrg fprintf (stderr, "<nil>\n");
27491debfc3dSmrg }
27501debfc3dSmrg
2751c0a68be4Smrg void
dump()2752c0a68be4Smrg bitmap_head::dump ()
2753c0a68be4Smrg {
2754c0a68be4Smrg debug (this);
2755c0a68be4Smrg }
2756c0a68be4Smrg
27571debfc3dSmrg #if CHECKING_P
27581debfc3dSmrg
27591debfc3dSmrg namespace selftest {
27601debfc3dSmrg
27611debfc3dSmrg /* Selftests for bitmaps. */
27621debfc3dSmrg
27631debfc3dSmrg /* Freshly-created bitmaps ought to be empty. */
27641debfc3dSmrg
27651debfc3dSmrg static void
test_gc_alloc()27661debfc3dSmrg test_gc_alloc ()
27671debfc3dSmrg {
27681debfc3dSmrg bitmap b = bitmap_gc_alloc ();
27691debfc3dSmrg ASSERT_TRUE (bitmap_empty_p (b));
27701debfc3dSmrg }
27711debfc3dSmrg
27721debfc3dSmrg /* Verify bitmap_set_range. */
27731debfc3dSmrg
27741debfc3dSmrg static void
test_set_range()27751debfc3dSmrg test_set_range ()
27761debfc3dSmrg {
27771debfc3dSmrg bitmap b = bitmap_gc_alloc ();
27781debfc3dSmrg ASSERT_TRUE (bitmap_empty_p (b));
27791debfc3dSmrg
27801debfc3dSmrg bitmap_set_range (b, 7, 5);
27811debfc3dSmrg ASSERT_FALSE (bitmap_empty_p (b));
27821debfc3dSmrg ASSERT_EQ (5, bitmap_count_bits (b));
27831debfc3dSmrg
27841debfc3dSmrg /* Verify bitmap_bit_p at the boundaries. */
27851debfc3dSmrg ASSERT_FALSE (bitmap_bit_p (b, 6));
27861debfc3dSmrg ASSERT_TRUE (bitmap_bit_p (b, 7));
27871debfc3dSmrg ASSERT_TRUE (bitmap_bit_p (b, 11));
27881debfc3dSmrg ASSERT_FALSE (bitmap_bit_p (b, 12));
27891debfc3dSmrg }
27901debfc3dSmrg
27911debfc3dSmrg /* Verify splitting a range into two pieces using bitmap_clear_bit. */
27921debfc3dSmrg
27931debfc3dSmrg static void
test_clear_bit_in_middle()27941debfc3dSmrg test_clear_bit_in_middle ()
27951debfc3dSmrg {
27961debfc3dSmrg bitmap b = bitmap_gc_alloc ();
27971debfc3dSmrg
27981debfc3dSmrg /* Set b to [100..200]. */
27991debfc3dSmrg bitmap_set_range (b, 100, 100);
28001debfc3dSmrg ASSERT_EQ (100, bitmap_count_bits (b));
28011debfc3dSmrg
28021debfc3dSmrg /* Clear a bit in the middle. */
28031debfc3dSmrg bool changed = bitmap_clear_bit (b, 150);
28041debfc3dSmrg ASSERT_TRUE (changed);
28051debfc3dSmrg ASSERT_EQ (99, bitmap_count_bits (b));
28061debfc3dSmrg ASSERT_TRUE (bitmap_bit_p (b, 149));
28071debfc3dSmrg ASSERT_FALSE (bitmap_bit_p (b, 150));
28081debfc3dSmrg ASSERT_TRUE (bitmap_bit_p (b, 151));
28091debfc3dSmrg }
28101debfc3dSmrg
28111debfc3dSmrg /* Verify bitmap_copy. */
28121debfc3dSmrg
28131debfc3dSmrg static void
test_copying()28141debfc3dSmrg test_copying ()
28151debfc3dSmrg {
28161debfc3dSmrg bitmap src = bitmap_gc_alloc ();
28171debfc3dSmrg bitmap_set_range (src, 40, 10);
28181debfc3dSmrg
28191debfc3dSmrg bitmap dst = bitmap_gc_alloc ();
28201debfc3dSmrg ASSERT_FALSE (bitmap_equal_p (src, dst));
28211debfc3dSmrg bitmap_copy (dst, src);
28221debfc3dSmrg ASSERT_TRUE (bitmap_equal_p (src, dst));
28231debfc3dSmrg
28241debfc3dSmrg /* Verify that we can make them unequal again... */
28251debfc3dSmrg bitmap_set_range (src, 70, 5);
28261debfc3dSmrg ASSERT_FALSE (bitmap_equal_p (src, dst));
28271debfc3dSmrg
28281debfc3dSmrg /* ...and that changing src after the copy didn't affect
28291debfc3dSmrg the other: */
28301debfc3dSmrg ASSERT_FALSE (bitmap_bit_p (dst, 70));
28311debfc3dSmrg }
28321debfc3dSmrg
28331debfc3dSmrg /* Verify bitmap_single_bit_set_p. */
28341debfc3dSmrg
28351debfc3dSmrg static void
test_bitmap_single_bit_set_p()28361debfc3dSmrg test_bitmap_single_bit_set_p ()
28371debfc3dSmrg {
28381debfc3dSmrg bitmap b = bitmap_gc_alloc ();
28391debfc3dSmrg
28401debfc3dSmrg ASSERT_FALSE (bitmap_single_bit_set_p (b));
28411debfc3dSmrg
28421debfc3dSmrg bitmap_set_range (b, 42, 1);
28431debfc3dSmrg ASSERT_TRUE (bitmap_single_bit_set_p (b));
28441debfc3dSmrg ASSERT_EQ (42, bitmap_first_set_bit (b));
28451debfc3dSmrg
28461debfc3dSmrg bitmap_set_range (b, 1066, 1);
28471debfc3dSmrg ASSERT_FALSE (bitmap_single_bit_set_p (b));
28481debfc3dSmrg ASSERT_EQ (42, bitmap_first_set_bit (b));
28491debfc3dSmrg
28501debfc3dSmrg bitmap_clear_range (b, 0, 100);
28511debfc3dSmrg ASSERT_TRUE (bitmap_single_bit_set_p (b));
28521debfc3dSmrg ASSERT_EQ (1066, bitmap_first_set_bit (b));
28531debfc3dSmrg }
28541debfc3dSmrg
28551debfc3dSmrg /* Run all of the selftests within this file. */
28561debfc3dSmrg
28571debfc3dSmrg void
bitmap_c_tests()28581debfc3dSmrg bitmap_c_tests ()
28591debfc3dSmrg {
28601debfc3dSmrg test_gc_alloc ();
28611debfc3dSmrg test_set_range ();
28621debfc3dSmrg test_clear_bit_in_middle ();
28631debfc3dSmrg test_copying ();
28641debfc3dSmrg test_bitmap_single_bit_set_p ();
28651debfc3dSmrg }
28661debfc3dSmrg
28671debfc3dSmrg } // namespace selftest
28681debfc3dSmrg #endif /* CHECKING_P */
28691debfc3dSmrg
28701debfc3dSmrg #include "gt-bitmap.h"
2871