X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fadt%2Fpdeq.c;h=dcf1143156513b569757c623ae55940f11fff342;hb=b1ac8fe5c7b3b462f66a99e6c780be9826414b7d;hp=e74d82a3953198a54298be665a404c6cf826e1be;hpb=0804355762ef7b45199c73902aaec3016edb1243;p=libfirm diff --git a/ir/adt/pdeq.c b/ir/adt/pdeq.c index e74d82a39..dcf114315 100644 --- a/ir/adt/pdeq.c +++ b/ir/adt/pdeq.c @@ -1,482 +1,456 @@ /* - * Project: libFIRM - * File name: ir/adt/pdeq.c - * Purpose: Pdeq --- double ended queue of generic pointers. - * Author: Christian von Roques - * Modified by: - * Created: 1999 by getting from fiasco - * CVS-ID: $Id$ - * Copyright: (c) 1995, 1996 Christian von Roques - * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. + * This file is part of libFirm. + * Copyright (C) 2012 University of Karlsruhe. */ +/** + * @file + * @brief double ended queue of generic pointers. + * @author Christian von Roques + * @date 1999 by getting from fiasco + */ +#include "config.h" -#ifdef HAVE_CONFIG_H -# include -#endif - -#include #include #include -#include -# ifdef HAVE_STRING_H -# include -# endif +#include +#include -#include "cookies.h" -#include "debug.h" +#include "fourcc.h" #include "pdeq.h" #include "xmalloc.h" +/* Pointer Double Ended Queue */ +#define PDEQ_MAGIC1 FOURCC('P','D','E','1') +#define PDEQ_MAGIC2 FOURCC('P','D','E','2') -/** Size of pdeq block cache */ +/** Size of pdeq block cache. */ #define TUNE_NSAVED_PDEQS 16 -/* # of data items in block */ -#define NDATA ((int)((PREF_MALLOC_SIZE - offsetof (pdeq, data)) / sizeof (void *))) +/** A size handled efficiently by malloc(), at least 1K. */ +#define PREF_MALLOC_SIZE 2048 + +/** + * Maximal number of data items in a pdeq chunk. + */ +#define NDATA ((PREF_MALLOC_SIZE - offsetof(pdeq, data)) / sizeof(void *)) #ifdef NDEBUG # define VRFY(dq) ((void)0) #else -# define VRFY(dq) \ - (d_(df_vrfy_level,1) ? _pdeq_vrfy ((dq)) : assert ((dq) && ((dq)->cookie == PDEQ_COOKIE1))) +# define VRFY(dq) assert((dq) && ((dq)->magic == PDEQ_MAGIC1)) #endif - +/** + * A pointer double ended queue. + * This structure is used as a list chunk either. + */ struct pdeq { #ifndef NDEBUG - unsigned cookie; + unsigned magic; /**< debug magic */ #endif - pdeq *l_end, *r_end; /* left and right ends of the deque */ - pdeq *l, *r; /* left and right neighbour */ - int n, p; - const void *data[1]; + pdeq *l_end, *r_end; /**< left and right ends of the queue */ + pdeq *l, *r; /**< left and right neighbor */ + size_t n; /**< number of elements in the current chunk */ + size_t p; /**< the read/write pointer */ + const void *data[1]; /**< storage for elements */ }; -/* cache of unused, pdeq blocks to speed up new_pdeq and del_pdeq. */ -/* +1 for compilers that can't grok empty arrays */ -pdeq *pdeq_block_cache[TUNE_NSAVED_PDEQS+1]; -unsigned pdeqs_cached; /* # pdeqs in pdeq_store */ +/** + * cache of unused, pdeq blocks to speed up new_pdeq and del_pdeq. + */ +static pdeq *pdeq_block_cache[TUNE_NSAVED_PDEQS]; +/** + * Number of pdeqs in pdeq_store. + */ +static unsigned pdeqs_cached; -static INLINE void -free_pdeq_block (pdeq *p) +/** + * Free a pdeq chunk, put in into the cache if possible. + * + * @param p The pdeq chunk. + */ +static inline void free_pdeq_block (pdeq *p) { #ifndef NDEBUG - p->cookie = 0xbadf00d1; + p->magic = 0xbadf00d1; #endif - if (pdeqs_cached < TUNE_NSAVED_PDEQS) { - if (d_ (df_pdeq, 2)) printf ("[%p ==> pdeq_block_cache] ", p); - pdeq_block_cache[pdeqs_cached++] = p; - } else { - if (d_ (df_pdeq, 2)) printf ("[%p ==> free] ", p); - xfree (p); - } + if (pdeqs_cached < TUNE_NSAVED_PDEQS) { + pdeq_block_cache[pdeqs_cached++] = p; + } else { + xfree (p); + } } - -static INLINE pdeq * -alloc_pdeq_block (void) -{ - pdeq *p; - if (TUNE_NSAVED_PDEQS && pdeqs_cached) { - p = pdeq_block_cache[--pdeqs_cached]; - if (d_ (df_pdeq, 2)) printf ("[pdeq_block_cache ==> %p] ", p); - } else { - p = xmalloc (PREF_MALLOC_SIZE); - if (d_ (df_pdeq, 2)) printf ("[malloc ==> %p] ", p); - } - return p; -} - - -#ifndef NDEBUG -void -_pdeq_vrfy (pdeq *dq) +/** + * Allocate a new pdeq chunk, get it from the cache if possible. + * + * @return A new pdeq chunk. + */ +static inline pdeq *alloc_pdeq_block (void) { - pdeq *q; - - if (d_ (df_pdeq, 5)) printf ("[pdeq_vrfy %p] ", dq); - - assert ( dq - && (dq->cookie == PDEQ_COOKIE1) - && (dq->l_end && dq->r_end)); - q = dq->l_end; - while (q) { - assert ( ((q == dq) || (q->cookie == PDEQ_COOKIE2)) - && ((q == dq->l_end) ^ (q->l!=0)) - && ((q == dq->r_end) ^ (q->r!=0)) - && (!q->l || (q == q->l->r)) - && ((q->n>=0) && (q->n<=NDATA)) - && ((q == dq->l_end) || (q == dq->r_end) || (q->n == NDATA)) - && ((q->p>=0) && (q->pr; - } + pdeq *p; + if (pdeqs_cached > 0) { + p = pdeq_block_cache[--pdeqs_cached]; + } else { + p = (pdeq*) xmalloc(PREF_MALLOC_SIZE); + } + return p; } -#endif - -pdeq * -new_pdeq (void) +/* Creates a new double ended pointer list. */ +pdeq *new_pdeq(void) { - pdeq *dq; + pdeq *dq; - dq = alloc_pdeq_block(); + dq = alloc_pdeq_block(); #ifndef NDEBUG - dq->cookie = PDEQ_COOKIE1; + dq->magic = PDEQ_MAGIC1; #endif - dq->l_end = dq->r_end = dq; - dq->l = dq->r = NULL; - dq->n = dq->p = 0; + dq->l_end = dq->r_end = dq; + dq->l = dq->r = NULL; + dq->n = dq->p = 0; - VRFY (dq); - if (d_ (df_pdeq, 1)) printf ("(new_pdeq ==> %p)\n", dq); - return dq; + VRFY(dq); + return dq; } - -pdeq * -new_pdeq1 (const void *x) +/* Creates a new double ended pointer list and puts an initial pointer element in. */ +pdeq *new_pdeq1(const void *x) { - return pdeq_putr (new_pdeq(), x); + return pdeq_putr(new_pdeq(), x); } - -void -del_pdeq (pdeq *dq) +/* Delete a double ended pointer list. */ +void del_pdeq(pdeq *dq) { - pdeq *q, *qq; - - VRFY (dq); + pdeq *q, *qq; - q = dq->l_end; /* left end of chain */ - /* pdeq trunk empty, but !pdeq_empty() ==> trunk not in chain */ - if (dq->n == 0 && dq->l_end != dq ) { - free_pdeq_block (dq); - } + VRFY(dq); - /* Free all blocks in the pdeq chain */ - do { - qq = q->r; - free_pdeq_block (q); - } while ((q = qq)); + q = dq->l_end; /* left end of chain */ + /* pdeq trunk empty, but !pdeq_empty() ==> trunk not in chain */ + if (dq->n == 0 && dq->l_end != dq ) { + free_pdeq_block(dq); + } - if (d_ (df_pdeq, 1)) printf ("(del_pdeq %p)\n", dq); + /* Free all blocks in the pdeq chain */ + do { + qq = q->r; + free_pdeq_block(q); + } while ((q = qq)); } - -bool -pdeq_empty (pdeq *dq) +/* Checks if a list is empty. */ +int pdeq_empty(pdeq *dq) { - VRFY (dq); - if (d_ (df_pdeq, 4)) printf ("(pdeq_empty %p ==> %d)\n", dq, dq->l_end->n == 0); - return dq->l_end->n == 0; + VRFY(dq); + return dq->l_end->n == 0; } - -int -pdeq_len (pdeq *dq) +/* Returns the length of a double ended pointer list. */ +size_t pdeq_len(pdeq *dq) { - int n; - pdeq *q; + size_t n; + pdeq *q; - VRFY (dq); + VRFY(dq); - n = 0; - q = dq->l_end; - do { - n += q->n; - q = q->r; - } while (q); + n = 0; + q = dq->l_end; + do { + n += q->n; + q = q->r; + } while (q); - if (d_ (df_pdeq, 4)) printf ("(pdeq_len %p ==> %d)\n", dq, n); - return n; + return n; } - -pdeq * -pdeq_putr (pdeq *dq, const void *x) +/* Add a pointer to the right site of a double ended pointer list. */ +pdeq *pdeq_putr(pdeq *dq, const void *x) { - pdeq *rdq; - int n; - bool pr = 0; + pdeq *rdq; + size_t n; - VRFY (dq); + VRFY(dq); - rdq = dq->r_end; - if (rdq->n >= NDATA) { /* tailblock full */ - pdeq *ndq; + rdq = dq->r_end; + if (rdq->n >= NDATA) { /* tailblock full */ + pdeq *ndq; - ndq = dq; /* try to reuse trunk, but ... */ - if (dq->n) { /* ... if trunk used */ - /* allocate and init new block */ - ndq = alloc_pdeq_block (); - pr = d_ (df_pdeq, 2); + ndq = dq; /* try to reuse trunk, but ... */ + if (dq->n) { /* ... if trunk used */ + /* allocate and init new block */ + ndq = alloc_pdeq_block(); #ifndef NDEBUG - ndq->cookie = PDEQ_COOKIE2; + ndq->magic = PDEQ_MAGIC2; #endif - ndq->l_end = ndq->r_end = NULL; - } + ndq->l_end = ndq->r_end = NULL; + } - ndq->r = NULL; - ndq->l = rdq; rdq->r = ndq; - ndq->n = 0; ndq->p = 0; - dq->r_end = ndq; - rdq = ndq; - } + ndq->r = NULL; + ndq->l = rdq; rdq->r = ndq; + ndq->n = 0; ndq->p = 0; + dq->r_end = ndq; + rdq = ndq; + } - n = rdq->n++ + rdq->p; - if (n >= NDATA) n -= NDATA; + n = rdq->n++ + rdq->p; + if (n >= NDATA) n -= NDATA; - rdq->data[n] = x; + rdq->data[n] = x; - VRFY (dq); - if (d_ (df_pdeq, 3) || pr) printf ("(pdeq_putr %p %p)\n", dq, x); - return dq; + VRFY(dq); + return dq; } - -pdeq * -pdeq_putl (pdeq *dq, const void *x) +/* Add a pointer to the left site of a double ended pointer list. */ +pdeq *pdeq_putl(pdeq *dq, const void *x) { - pdeq *ldq; - int p; - bool pr = 0; + pdeq *ldq; + size_t p; - VRFY (dq); + VRFY(dq); - ldq = dq->l_end; - if (ldq->n >= NDATA) { /* headblock full */ - pdeq *ndq; + ldq = dq->l_end; + if (ldq->n >= NDATA) { /* headblock full */ + pdeq *ndq; - ndq = dq; /* try to reuse trunk, but ... */ - if (dq->n) { /* ... if trunk used */ - /* allocate and init new block */ - ndq = alloc_pdeq_block (); - pr = d_ (df_pdeq, 2); + ndq = dq; /* try to reuse trunk, but ... */ + if (dq->n) { /* ... if trunk used */ + /* allocate and init new block */ + ndq = alloc_pdeq_block(); #ifndef NDEBUG - ndq->cookie = PDEQ_COOKIE2; + ndq->magic = PDEQ_MAGIC2; #endif - ndq->l_end = ndq->r_end = NULL; - } - - ndq->l = NULL; - ndq->r = ldq; ldq->l = ndq; - ndq->n = 0; ndq->p = 0; - dq->l_end = ndq; - ldq = ndq; - } - - ldq->n++; - p = ldq->p - 1; - if (p < 0) p += NDATA; - ldq->p = p; - - ldq->data[p] = x; - - VRFY (dq); - if (d_ (df_pdeq, 3) || pr) printf ("(pdeq_putl %p %p)\n", dq, x); - return dq; + ndq->l_end = ndq->r_end = NULL; + } + + ndq->l = NULL; + ndq->r = ldq; ldq->l = ndq; + ndq->n = 0; ndq->p = 0; + dq->l_end = ndq; + ldq = ndq; + } + + ldq->n++; + if (ldq->p == 0) + p = NDATA; + else + p = ldq->p - 1; + ldq->p = p; + + ldq->data[p] = x; + + VRFY(dq); + return dq; } - -void * -pdeq_getr (pdeq *dq) +/* Retrieve a pointer from the right site of a double ended pointer list. */ +void *pdeq_getr(pdeq *dq) { - pdeq *rdq; - const void *x; - int n; - bool pr = 0; - - VRFY (dq); - assert (dq->l_end->n); - - rdq = dq->r_end; - n = rdq->p + --rdq->n; - if (n>=NDATA) n -= NDATA; - x = rdq->data[n]; - - if (rdq->n == 0) { - if (rdq->l) { - dq->r_end = rdq->l; - rdq->l->r = NULL; - rdq->l = NULL; - } else { - dq->r_end = dq->l_end = dq; - } - if (dq != rdq) { - free_pdeq_block (rdq); - pr = d_ (df_pdeq, 2); - } - } - - VRFY (dq); - if (d_ (df_pdeq, 3) || pr) printf ("(pdeq_getr %p ==> %p)\n", dq, x); - return (void *)x; + pdeq *rdq; + const void *x; + size_t n; + + VRFY(dq); + assert(dq->l_end->n); + + rdq = dq->r_end; + n = rdq->p + --rdq->n; + if (n >= NDATA) n -= NDATA; + x = rdq->data[n]; + + if (rdq->n == 0) { + if (rdq->l) { + dq->r_end = rdq->l; + rdq->l->r = NULL; + rdq->l = NULL; + } else { + dq->r_end = dq->l_end = dq; + } + if (dq != rdq) { + free_pdeq_block(rdq); + } + } + + VRFY(dq); + return (void *)x; } - -void * -pdeq_getl (pdeq *dq) +/* Retrieve a pointer from the left site of a double ended pointer list. */ +void *pdeq_getl(pdeq *dq) { - pdeq *ldq; - const void *x; - int p; - bool pr = 0; - - VRFY (dq); - assert (dq->l_end->n); - - ldq = dq->l_end; - p = ldq->p; - x = ldq->data[p]; - if (++p >= NDATA) p = 0; - ldq->p = p; - - if (--ldq->n == 0) { - if (ldq->r) { - dq->l_end = ldq->r; - ldq->r->l = NULL; - ldq->r = NULL; - } else { - dq->l_end = dq->r_end = dq; - } - if (dq != ldq) { - free_pdeq_block (ldq); - pr = d_ (df_pdeq, 2); - } - } - - VRFY (dq); - if (d_ (df_pdeq, 3) || pr) printf ("(pdeq_getl %p ==> %p)\n", dq, x); - return (void *)x; + pdeq *ldq; + const void *x; + size_t p; + + VRFY(dq); + assert(dq->l_end->n); + + ldq = dq->l_end; + p = ldq->p; + x = ldq->data[p]; + if (++p >= NDATA) p = 0; + ldq->p = p; + + if (--ldq->n == 0) { + if (ldq->r) { + dq->l_end = ldq->r; + ldq->r->l = NULL; + ldq->r = NULL; + } else { + dq->l_end = dq->r_end = dq; + } + if (dq != ldq) { + free_pdeq_block(ldq); + } + } + + VRFY(dq); + return (void *)x; } - -bool -pdeq_contains (pdeq *dq, const void *x) +/* + * Returns non-zero if a double ended pointer list + * contains a pointer x. + */ +int pdeq_contains(pdeq *dq, const void *x) { - pdeq *q; - - VRFY (dq); + pdeq *q; - q = dq->l_end; - do { - int p, ep; + VRFY(dq); - p = q->p; ep = p + q->n; + q = dq->l_end; + do { + size_t p, ep; - if (ep > NDATA) { - do if (q->data[p] == x) goto found; while (++p < NDATA); - p = 0; - ep -= NDATA; - } + p = q->p; ep = p + q->n; - while (p < ep) if (q->data[p++] == x) goto found; + if (ep > NDATA) { + do { + if (q->data[p] == x) return 1; + } while (++p < NDATA); + p = 0; + ep -= NDATA; + } - q = q->r; - } while (q); + while (p < ep) { + if (q->data[p++] == x) return 1; + } - if (d_ (df_pdeq, 3)) printf ("(pdeq_contains %p %p ==> 0)\n", dq, x); - return 0; + q = q->r; + } while (q); -found: /* The two gotos can be optimized away, if !DEBUG */ - if (d_ (df_pdeq, 3)) printf ("(pdeq_contains %p %p ==> 1)\n", dq, x); - return 1; + return 0; } - -void * -pdeq_search (pdeq *dq, cmp_fun cmp, const void *key) +/* + * Search a key in a double ended pointer list, the search + * is controlled by a compare function. + * An element is found, if the compare function returns 0. + * The search is started from the left site of the list. + */ +void *pdeq_search(pdeq *dq, cmp_fun cmp, const void *key) { - pdeq *q; - int p; - - VRFY (dq); + pdeq *q; + size_t p; - q = dq->l_end; - do { - int ep; + VRFY(dq); - p = q->p; ep = p + q->n; + q = dq->l_end; + do { + size_t ep; - if (ep > NDATA) { - do if (!cmp (q->data[p], key)) goto found; while (++p < NDATA); - p = 0; - ep -= NDATA; - } + p = q->p; ep = p + q->n; - while (p < ep) if (!cmp (q->data[p++], key)) goto found; + if (ep > NDATA) { + do { + if (!cmp(q->data[p], key)) return (void *)q->data[p-1]; + } while (++p < NDATA); + p = 0; + ep -= NDATA; + } - q = q->r; - } while (q); + while (p < ep) { + if (!cmp(q->data[p++], key)) return (void *)q->data[p-1]; + } - if (d_ (df_pdeq, 3)) printf ("(pdeq_search %p %p %p ==> 0)\n", dq, cmp, key); - return NULL; + q = q->r; + } while (q); -found: /* The two gotos can be optimized away, if !DEBUG */ - if (d_ (df_pdeq, 3)) printf ("(pdeq_contains %p %p %p ==> %p)\n", - dq, cmp, key, q->data[p]); - return (void *)q->data[p-1]; + return NULL; } - -void ** -pdeq_copyl (pdeq *dq, const void **dst) +/* + * Convert the double ended pointer list into a linear array beginning from + * left, the first element in the linear array will be the left one. + */ +void **pdeq_copyl(pdeq *dq, const void **dst) { - pdeq *q; - const void **d = dst; + pdeq *q; + const void **d = dst; - VRFY (dq); + VRFY(dq); - q = dq->l_end; - while (q) { - int p, n; + q = dq->l_end; + while (q) { + size_t p, n; - p = q->p; n = q->n; + p = q->p; n = q->n; - if (n + p > NDATA) { - int nn = NDATA - p; - memcpy (d, &q->data[p], nn * sizeof (void *)); d += nn; - p = 0; n -= nn; - } + if (n + p > NDATA) { + /* p is always < NDATA */ + size_t nn = NDATA - p; + memcpy((void *) d, &q->data[p], nn * sizeof(void *)); d += nn; + p = 0; n -= nn; + } - memcpy (d, &q->data[p], n * sizeof (void *)); d += n; + memcpy((void *) d, &q->data[p], n * sizeof(void *)); d += n; - q = q->r; - } + q = q->r; + } - if (d_ (df_pdeq, 3)) printf ("(pdeq_copyl %p %p ==> %p)\n", dq, dst, d); - return (void **)dst; + return (void **)dst; } - -void ** -pdeq_copyr (pdeq *dq, const void **dst) +/* + * Convert the double ended pointer list into a linear array beginning from + * right, the first element in the linear array will be the right one. + */ +void **pdeq_copyr(pdeq *dq, const void **dst) { - pdeq *q; - const void **d = dst; - - VRFY (dq); - - q = dq->r_end; - while (q) { - int p, i; - - p = q->p; i = q->n + p - 1; - if (i >= NDATA) { - i -= NDATA; - do *d++ = q->data[i]; while (--i >= 0); - i = NDATA - 1; - } - - do *d++ = q->data[i]; while (--i >= p); - - q = q->l; - } - - if (d_ (df_pdeq, 3)) printf ("(pdeq_copyr %p %p ==> %p)\n", dq, dst, d); - return (void **)dst; + pdeq *q; + const void **d = dst; + + VRFY(dq); + + q = dq->r_end; + while (q) { + size_t p, i; + + p = q->p; i = q->n + p - 1; + if (i >= NDATA) { + i -= NDATA; + for (;; --i) { + *d++ = q->data[i]; + if (i == 0) + break; + } + i = NDATA - 1; + } + + for (;; --i) { + *d++ = q->data[i]; + if (i <= p) + break; + } + + q = q->l; + } + + return (void **)dst; }