1 /* Functions to support general ended bitmaps.
2 Copyright (C) 1997, 1998 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
27 #include "basic-block.h"
29 /* Obstack to allocate bitmap elements from. */
30 static struct obstack bitmap_obstack
;
31 static int bitmap_obstack_init
= FALSE
;
38 #define INLINE __inline__
43 bitmap_element bitmap_zero
; /* An element of all zero bits. */
44 bitmap_element
*bitmap_free
; /* Freelist of bitmap elements. */
46 static void bitmap_element_free
PROTO((bitmap
, bitmap_element
*));
47 static bitmap_element
*bitmap_element_allocate
PROTO((void));
48 static int bitmap_element_zerop
PROTO((bitmap_element
*));
49 static void bitmap_element_link
PROTO((bitmap
, bitmap_element
*));
50 static bitmap_element
*bitmap_find_bit
PROTO((bitmap
, unsigned int));
52 /* Free a bitmap element */
55 bitmap_element_free (head
, elt
)
59 bitmap_element
*next
= elt
->next
;
60 bitmap_element
*prev
= elt
->prev
;
68 if (head
->first
== elt
)
71 /* Since the first thing we try is to insert before current,
72 make current the next entry in preference to the previous. */
73 if (head
->current
== elt
)
74 head
->current
= next
!= 0 ? next
: prev
;
76 elt
->next
= bitmap_free
;
80 /* Allocate a bitmap element. The bits are cleared, but nothing else is. */
82 static INLINE bitmap_element
*
83 bitmap_element_allocate ()
85 bitmap_element
*element
;
86 #if BITMAP_ELEMENT_WORDS != 2
92 element
= bitmap_free
;
93 bitmap_free
= element
->next
;
97 /* We can't use gcc_obstack_init to initialize the obstack since
98 print-rtl.c now calls bitmap functions, and bitmap is linked
99 into the gen* functions. */
100 if (!bitmap_obstack_init
)
102 bitmap_obstack_init
= TRUE
;
104 /* Let particular systems override the size of a chunk. */
105 #ifndef OBSTACK_CHUNK_SIZE
106 #define OBSTACK_CHUNK_SIZE 0
108 /* Let them override the alloc and free routines too. */
109 #ifndef OBSTACK_CHUNK_ALLOC
110 #define OBSTACK_CHUNK_ALLOC xmalloc
112 #ifndef OBSTACK_CHUNK_FREE
113 #define OBSTACK_CHUNK_FREE free
116 #if !defined(__GNUC__) || (__GNUC__ < 2)
117 #define __alignof__(type) 0
120 obstack_specify_allocation (&bitmap_obstack
, OBSTACK_CHUNK_SIZE
,
121 __alignof__ (bitmap_element
),
122 (void *(*) ()) OBSTACK_CHUNK_ALLOC
,
123 (void (*) ()) OBSTACK_CHUNK_FREE
);
126 element
= (bitmap_element
*) obstack_alloc (&bitmap_obstack
,
127 sizeof (bitmap_element
));
130 #if BITMAP_ELEMENT_WORDS == 2
131 element
->bits
[0] = element
->bits
[1] = 0;
133 for (i
= 0; i
< BITMAP_ELEMENT_WORDS
; i
++)
134 element
->bits
[i
] = 0;
140 /* Return nonzero if all bits in an element are zero. */
143 bitmap_element_zerop (element
)
144 bitmap_element
*element
;
146 #if BITMAP_ELEMENT_WORDS == 2
147 return (element
->bits
[0] | element
->bits
[1]) == 0;
151 for (i
= 0; i
< BITMAP_ELEMENT_WORDS
; i
++)
152 if (element
->bits
[i
] != 0)
159 /* Link the bitmap element into the current bitmap linked list. */
162 bitmap_element_link (head
, element
)
164 bitmap_element
*element
;
166 unsigned int indx
= element
->indx
;
169 /* If this is the first and only element, set it in. */
170 if (head
->first
== 0)
172 element
->next
= element
->prev
= 0;
173 head
->first
= element
;
176 /* If this index is less than that of the current element, it goes someplace
177 before the current element. */
178 else if (indx
< head
->indx
)
180 for (ptr
= head
->current
;
181 ptr
->prev
!= 0 && ptr
->prev
->indx
> indx
;
186 ptr
->prev
->next
= element
;
188 head
->first
= element
;
190 element
->prev
= ptr
->prev
;
195 /* Otherwise, it must go someplace after the current element. */
198 for (ptr
= head
->current
;
199 ptr
->next
!= 0 && ptr
->next
->indx
< indx
;
204 ptr
->next
->prev
= element
;
206 element
->next
= ptr
->next
;
211 /* Set up so this is the first element searched. */
212 head
->current
= element
;
216 /* Clear a bitmap by freeing the linked list. */
222 bitmap_element
*element
, *next
;
224 for (element
= head
->first
; element
!= 0; element
= next
)
226 next
= element
->next
;
227 element
->next
= bitmap_free
;
228 bitmap_free
= element
;
231 head
->first
= head
->current
= 0;
234 /* Copy a bitmap to another bitmap */
237 bitmap_copy (to
, from
)
241 bitmap_element
*from_ptr
, *to_ptr
= 0;
242 #if BITMAP_ELEMENT_WORDS != 2
248 /* Copy elements in forward direction one at a time */
249 for (from_ptr
= from
->first
; from_ptr
; from_ptr
= from_ptr
->next
)
251 bitmap_element
*to_elt
= bitmap_element_allocate ();
253 to_elt
->indx
= from_ptr
->indx
;
255 #if BITMAP_ELEMENT_WORDS == 2
256 to_elt
->bits
[0] = from_ptr
->bits
[0];
257 to_elt
->bits
[1] = from_ptr
->bits
[1];
259 for (i
= 0; i
< BITMAP_ELEMENT_WORDS
; i
++)
260 to_elt
->bits
[i
] = from_ptr
->bits
[i
];
263 /* Here we have a special case of bitmap_element_link, for the case
264 where we know the links are being entered in sequence. */
267 to
->first
= to
->current
= to_elt
;
268 to
->indx
= from_ptr
->indx
;
269 to_elt
->next
= to_elt
->prev
= 0;
273 to_elt
->prev
= to_ptr
;
275 to_ptr
->next
= to_elt
;
282 /* Find a bitmap element that would hold a bitmap's bit.
283 Update the `current' field even if we can't find an element that
284 would hold the bitmap's bit to make eventual allocation
287 static INLINE bitmap_element
*
288 bitmap_find_bit (head
, bit
)
292 bitmap_element
*element
;
293 unsigned HOST_WIDE_INT indx
= bit
/ BITMAP_ELEMENT_ALL_BITS
;
295 if (head
->current
== 0)
298 if (head
->indx
> indx
)
299 for (element
= head
->current
;
300 element
->prev
!= 0 && element
->indx
> indx
;
301 element
= element
->prev
)
305 for (element
= head
->current
;
306 element
->next
!= 0 && element
->indx
< indx
;
307 element
= element
->next
)
310 /* `element' is the nearest to the one we want. If it's not the one we
311 want, the one we want doesn't exist. */
312 head
->current
= element
;
313 head
->indx
= element
->indx
;
314 if (element
!= 0 && element
->indx
!= indx
)
320 /* Clear a single bit in a bitmap. */
323 bitmap_clear_bit (head
, bit
)
327 bitmap_element
*ptr
= bitmap_find_bit (head
, bit
);
331 unsigned bit_num
= bit
% (unsigned) HOST_BITS_PER_WIDE_INT
;
332 unsigned word_num
= ((bit
/ (unsigned) HOST_BITS_PER_WIDE_INT
)
333 % BITMAP_ELEMENT_WORDS
);
334 ptr
->bits
[word_num
] &= ~ (((unsigned HOST_WIDE_INT
) 1) << bit_num
);
336 /* If we cleared the entire word, free up the element */
337 if (bitmap_element_zerop (ptr
))
338 bitmap_element_free (head
, ptr
);
343 /* Set a single bit in a bitmap. */
346 bitmap_set_bit (head
, bit
)
350 bitmap_element
*ptr
= bitmap_find_bit (head
, bit
);
352 = ((bit
/ (unsigned) HOST_BITS_PER_WIDE_INT
) % BITMAP_ELEMENT_WORDS
);
353 unsigned bit_num
= bit
% (unsigned) HOST_BITS_PER_WIDE_INT
;
354 unsigned HOST_WIDE_INT bit_val
= ((unsigned HOST_WIDE_INT
) 1) << bit_num
;
358 ptr
= bitmap_element_allocate ();
359 ptr
->indx
= bit
/ BITMAP_ELEMENT_ALL_BITS
;
360 ptr
->bits
[word_num
] = bit_val
;
361 bitmap_element_link (head
, ptr
);
364 ptr
->bits
[word_num
] |= bit_val
;
367 /* Return whether a bit is set within a bitmap. */
370 bitmap_bit_p (head
, bit
)
378 ptr
= bitmap_find_bit (head
, bit
);
382 bit_num
= bit
% (unsigned) HOST_BITS_PER_WIDE_INT
;
384 = ((bit
/ (unsigned) HOST_BITS_PER_WIDE_INT
) % BITMAP_ELEMENT_WORDS
);
387 (ptr
->bits
[word_num
] & (((unsigned HOST_WIDE_INT
) 1) << bit_num
)) != 0;
390 /* Store in bitmap TO the result of combining bitmap FROM1 and
391 FROM2 using a specific bit manipulation. */
394 bitmap_operation (to
, from1
, from2
, operation
)
398 enum bitmap_bits operation
;
400 bitmap_element
*delete_list
= 0;
401 bitmap_element
*from1_ptr
= from1
->first
;
402 bitmap_element
*from2_ptr
= from2
->first
;
404 = (from1_ptr
) ? from1_ptr
->indx
: ~ (unsigned HOST_WIDE_INT
) 0;
406 = (from2_ptr
) ? from2_ptr
->indx
: ~ (unsigned HOST_WIDE_INT
) 0;
407 bitmap_element
*to_ptr
= 0;
408 bitmap_element
*from1_tmp
;
409 bitmap_element
*from2_tmp
;
411 #if BITMAP_ELEMENT_WORDS != 2
415 /* To simplify things, always create a new list. If the old list was one
416 of the inputs, free it later. Otherwise, free it now. */
417 if (to
== from1
|| to
== from2
)
419 delete_list
= to
->first
;
420 to
->first
= to
->current
= 0;
425 while (from1_ptr
!= 0 || from2_ptr
!= 0)
427 /* Figure out whether we need to substitute zero elements for
432 from1_tmp
= from1_ptr
;
433 from2_tmp
= from2_ptr
;
434 from1_ptr
= from1_ptr
->next
;
435 indx1
= (from1_ptr
) ? from1_ptr
->indx
: ~ (unsigned HOST_WIDE_INT
) 0;
436 from2_ptr
= from2_ptr
->next
;
437 indx2
= (from2_ptr
) ? from2_ptr
->indx
: ~ (unsigned HOST_WIDE_INT
) 0;
439 else if (indx1
< indx2
)
442 from1_tmp
= from1_ptr
;
443 from2_tmp
= &bitmap_zero
;
444 from1_ptr
= from1_ptr
->next
;
445 indx1
= (from1_ptr
) ? from1_ptr
->indx
: ~ (unsigned HOST_WIDE_INT
) 0;
450 from1_tmp
= &bitmap_zero
;
451 from2_tmp
= from2_ptr
;
452 from2_ptr
= from2_ptr
->next
;
453 indx2
= (from2_ptr
) ? from2_ptr
->indx
: ~ (unsigned HOST_WIDE_INT
) 0;
457 to_ptr
= bitmap_element_allocate ();
459 /* Do the operation, and if any bits are set, link it into the
467 #if BITMAP_ELEMENT_WORDS == 2
468 to_ptr
->bits
[0] = from1_tmp
->bits
[0] & from2_tmp
->bits
[0];
469 to_ptr
->bits
[1] = from1_tmp
->bits
[1] & from2_tmp
->bits
[1];
471 for (i
= BITMAP_ELEMENT_WORDS
- 1; i
>= 0; i
--)
472 to_ptr
->bits
[i
] = from1_tmp
->bits
[i
] & from2_tmp
->bits
[i
];
476 case BITMAP_AND_COMPL
:
477 #if BITMAP_ELEMENT_WORDS == 2
478 to_ptr
->bits
[0] = from1_tmp
->bits
[0] & ~ from2_tmp
->bits
[0];
479 to_ptr
->bits
[1] = from1_tmp
->bits
[1] & ~ from2_tmp
->bits
[1];
481 for (i
= BITMAP_ELEMENT_WORDS
- 1; i
>= 0; i
--)
482 to_ptr
->bits
[i
] = from1_tmp
->bits
[i
] & ~ from2_tmp
->bits
[i
];
487 #if BITMAP_ELEMENT_WORDS == 2
488 to_ptr
->bits
[0] = from1_tmp
->bits
[0] | from2_tmp
->bits
[0];
489 to_ptr
->bits
[1] = from1_tmp
->bits
[1] | from2_tmp
->bits
[1];
491 for (i
= BITMAP_ELEMENT_WORDS
- 1; i
>= 0; i
--)
492 to_ptr
->bits
[i
] = from1_tmp
->bits
[i
] | from2_tmp
->bits
[i
];
497 if (! bitmap_element_zerop (to_ptr
))
500 bitmap_element_link (to
, to_ptr
);
505 /* If we have an unallocated element due to the last element being 0,
506 release it back to the free pool. Don't bother calling
507 bitmap_element_free since it was never linked into a bitmap. */
510 to_ptr
->next
= bitmap_free
;
511 bitmap_free
= to_ptr
;
514 /* If the output bitmap was one of the inputs, free up its
515 elements now that we're done. */
516 for (; delete_list
!= 0; delete_list
= to_ptr
)
518 to_ptr
= delete_list
->next
;
519 delete_list
->next
= bitmap_free
;
520 bitmap_free
= delete_list
;
524 /* Or into bitmap TO bitmap FROM1 and'ed with the complement of
528 bitmap_ior_and_compl (to
, from1
, from2
)
535 tmp
.first
= tmp
.current
= 0;
537 bitmap_operation (&tmp
, from1
, from2
, BITMAP_AND_COMPL
);
538 bitmap_operation (to
, to
, &tmp
, BITMAP_IOR
);
542 /* Initialize a bitmap header. */
545 bitmap_initialize (head
)
548 head
->first
= head
->current
= 0;
553 /* Debugging function to print out the contents of a bitmap. */
556 bitmap_debug_file (file
, head
)
562 fprintf (file
, "\nfirst = ");
563 fprintf (file
, HOST_PTR_PRINTF
, head
->first
);
564 fprintf (file
, " current = ");
565 fprintf (file
, HOST_PTR_PRINTF
, head
->current
);
566 fprintf (file
, " indx = %u\n", head
->indx
);
568 for (ptr
= head
->first
; ptr
; ptr
= ptr
->next
)
572 fprintf (file
, "\t");
573 fprintf (file
, HOST_PTR_PRINTF
, ptr
);
574 fprintf (file
, " next = ");
575 fprintf (file
, HOST_PTR_PRINTF
, ptr
->next
);
576 fprintf (file
, " prev = ");
577 fprintf (file
, HOST_PTR_PRINTF
, ptr
->prev
);
578 fprintf (file
, " indx = %u\n\t\tbits = {", ptr
->indx
);
580 for (i
= 0; i
< BITMAP_ELEMENT_WORDS
; i
++)
581 for (j
= 0; j
< HOST_BITS_PER_WIDE_INT
; j
++)
582 if ((ptr
->bits
[i
] & (((unsigned HOST_WIDE_INT
) 1) << j
)) != 0)
586 fprintf (file
, "\n\t\t\t");
590 fprintf (file
, " %u", (ptr
->indx
* BITMAP_ELEMENT_ALL_BITS
591 + i
* HOST_BITS_PER_WIDE_INT
+ j
));
595 fprintf (file
, " }\n");
599 /* Function to be called from the debugger to print the contents
606 bitmap_debug_file (stdout
, head
);
609 /* Function to print out the contents of a bitmap. Unlike bitmap_debug_file,
610 it does not print anything but the bits. */
613 bitmap_print (file
, head
, prefix
, suffix
)
622 fputs (prefix
, file
);
623 EXECUTE_IF_SET_IN_BITMAP (head
, 0, i
,
625 fprintf (file
, "%s%d", comma
, i
);
628 fputs (suffix
, file
);
631 /* Release any memory allocated by bitmaps. */
634 bitmap_release_memory ()
637 if (bitmap_obstack_init
)
639 bitmap_obstack_init
= FALSE
;
640 obstack_free (&bitmap_obstack
, NULL_PTR
);