Added sorted array sets.
authorSebastian Hack <hack@ipd.info.uni-karlsruhe.de>
Wed, 11 Jul 2007 22:47:45 +0000 (22:47 +0000)
committerSebastian Hack <hack@ipd.info.uni-karlsruhe.de>
Wed, 11 Jul 2007 22:47:45 +0000 (22:47 +0000)
Adjusted nodesets to it but it is still deactivated.
See macro at the top of irnodeset.h

[r15065]

include/libfirm/adt/arrayset.h [new file with mode: 0644]
ir/adt/arrayset.c [new file with mode: 0644]
ir/ir/irnodeset.c
ir/ir/irnodeset.h

diff --git a/include/libfirm/adt/arrayset.h b/include/libfirm/adt/arrayset.h
new file mode 100644 (file)
index 0000000..e17cb86
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ *
+ * This file is part of libFirm.
+ *
+ * This file may be distributed and/or modified under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * Licensees holding valid libFirm Professional Edition licenses may use
+ * this file in accordance with the libFirm Commercial License.
+ * Agreement provided with the Software.
+ *
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ */
+
+/**
+ * @file   arrayset.h
+ * @date   11.07.2007
+ * @author Sebastian Hack
+ */
+
+struct HashSet {
+       ValueType *arr;
+#ifndef NDEBUG
+       unsigned in_order : 1;
+#endif
+#ifdef ADDITIONAL_DATA
+       ADDITIONAL_DATA
+#endif
+};
+
+struct HashSetIterator {
+       ValueType *arr;
+       int curr;
+};
diff --git a/ir/adt/arrayset.c b/ir/adt/arrayset.c
new file mode 100644 (file)
index 0000000..ab3d7d4
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ *
+ * This file is part of libFirm.
+ *
+ * This file may be distributed and/or modified under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * Licensees holding valid libFirm Professional Edition licenses may use
+ * this file in accordance with the libFirm Commercial License.
+ * Agreement provided with the Software.
+ *
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ */
+
+/**
+ * @file   arrayset.c
+ * @brief  Implementation of sets with sorted arrays.
+ * @date   11.07.2007
+ * @author Sebastian Hack
+ *
+ * Follows the same API/specialization scheme as hashset.c and is thus interchangable.
+ * To remain compatible, all specializations as in hashset.c must be done.
+ * Additionally, we need a ValueCmp macro comapring two values not only for equality.
+ * That macro follows the same scheme as the compare functions in qsort(3).
+ */
+
+#ifdef HashSet
+
+#include "firm_config.h"
+#include "array.h"
+
+static INLINE int hashset_bsearch(ValueType *arr, const ValueType elm)
+{
+       int res = 0;
+       int lo  = 0;
+       int hi  = ARR_LEN(arr);
+
+       while(lo < hi) {
+               int md     = lo + ((hi - lo) >> 1);
+               int cmp    = ValueCmp(arr[md], elm);
+
+               if(cmp < 0)
+                       lo = md + 1;
+               else if(cmp > 0)
+                       hi = md;
+               else {
+                       res = md;
+                       break;
+               }
+
+               res = lo;
+       }
+
+       return res;
+}
+
+static INLINE int hashset_is_at(ValueType *arr, int idx, const ValueType what)
+{
+       return idx < ARR_LEN(arr) && ValueCmp(arr[idx], what) == 0;
+}
+
+void hashset_init_size(HashSet *set, size_t expected_elements)
+{
+       set->arr = NEW_ARR_F(ValueType, expected_elements);
+#ifndef NDEBUG
+       set->in_order = 1;
+#endif
+       ARR_SHRINKLEN(set->arr, 0);
+}
+
+void hashset_init(HashSet *set)
+{
+       hashset_init_size(set, 16);
+}
+
+void hashset_destroy(HashSet *set)
+{
+       DEL_ARR_F(set->arr);
+}
+
+int hashset_insert(HashSet *set, ValueType elt)
+{
+       ValueType *arr = set->arr;
+       int i, idx     = hashset_bsearch(arr, elt);
+
+#ifndef NDEBUG
+       assert(set->in_order);
+#endif
+       if (!hashset_is_at(arr, idx, elt)) {
+               ARR_EXTEND(ValueType, set->arr, 1);
+               arr = set->arr;
+               for (i = ARR_LEN(arr) - 1; i > idx; --i)
+                       arr[i] = arr[i - 1];
+               arr[idx] = elt;
+               return 1;
+       }
+
+       return 0;
+}
+
+void hashset_insert_quick(HashSet *set, ValueType elt)
+{
+       ValueType *arr = set->arr;
+       ARR_EXTEND(ValueType, set->arr, 1);
+       arr = set->arr;
+       arr[ARR_LEN(arr) - 1] = elt;
+}
+
+static INLINE int _hashset_remove_idx(ValueType *arr, int idx)
+{
+       int n;
+
+       for (n = ARR_LEN(arr) - 1; idx < n; ++idx)
+               arr[idx] = arr[idx + 1];
+
+       return n;
+}
+
+void hashset_remove(HashSet *set, const ValueType elt)
+{
+       ValueType *arr = set->arr;
+       int idx        = hashset_bsearch(arr, elt);
+
+#ifndef NDEBUG
+       assert(set->in_order);
+#endif
+       if (hashset_is_at(arr, idx, elt)) {
+               int new_len = _hashset_remove_idx(arr, idx);
+               ARR_SHRINKLEN(arr, new_len);
+       }
+}
+
+void hashset_remove_quick(HashSet *set, const ValueType elt)
+{
+       ValueType *arr = set->arr;
+       int idx        = hashset_bsearch(arr, elt);
+
+#ifndef NDEBUG
+       set->in_order = 0;
+#endif
+       if (hashset_is_at(arr, idx, elt)) {
+               int n = ARR_LEN(arr);
+               if (idx < n - 1)
+                       arr[idx] = arr[n - 1];
+               ARR_SHRINKLEN(arr, n - 1);
+       }
+}
+
+void hashset_fixup(HashSet *set)
+{
+       ValueType *arr = set->arr;
+       ValueType *tmp;
+       int i, n;
+
+       CLONE_ARR_A(ValueType, tmp, arr);
+
+       memcpy(tmp, arr, n * sizeof(arr[0]));
+       ARR_SHRINKLEN(arr, 0);
+       for (i = 0, n = ARR_LEN(arr); i < n; ++i)
+               hashset_insert(set, tmp[0]);
+#ifndef NDEBUG
+       set->in_order = 1;
+#endif
+}
+
+ValueType hashset_find(const HashSet *set, const ValueType elt)
+{
+       int idx = hashset_bsearch(set->arr, elt);
+#ifndef NDEBUG
+       assert(set->in_order);
+#endif
+       return hashset_is_at(set->arr, idx, elt) ? set->arr[idx] : NullValue;
+}
+
+size_t hashset_size(const HashSet *set)
+{
+       return ARR_LEN(set->arr);
+}
+
+void hashset_iterator_init(HashSetIterator *iter, const HashSet *set)
+{
+       iter->arr  = set->arr;
+       iter->curr = -1;
+}
+
+ValueType ir_nodeset_iterator_next(HashSetIterator *iter)
+{
+       ++iter->curr;
+       return iter->curr < ARR_LEN(iter->arr) ? iter->arr[iter->curr]  : NullValue;
+}
+
+void hashset_remove_iterator(HashSet *set, const HashSetIterator *iter)
+{
+       (void) set;
+       (void) _hashset_remove_idx(iter->arr, iter->curr);
+       ARR_SHRINKLEN(iter->arr, ARR_LEN(iter->arr) - 1);
+}
+
+#endif
index bac3fb0..ec325f5 100644 (file)
@@ -45,6 +45,7 @@
 #endif
 #define KeysEqual(this,key1,key2) (key1) == (key2)
 #define SetRangeEmpty(ptr,size)   memset(ptr, 0, (size) * sizeof((ptr)[0]))
+#define ValueCmp(a,b)             ((int) get_irn_idx(a) - (int) get_irn_idx(b))
 
 #define hashset_init            _ir_nodeset_init
 #define hashset_init_size       ir_nodeset_init_size
 #define hashset_iterator_next   ir_nodeset_iterator_next
 #define hashset_remove_iterator ir_nodeset_remove_iterator
 
+#ifdef IR_NODESET_USE_ORDERED_SETS
+
+#define hashset_insert_quick    ir_nodeset_insert_quick
+#define hashset_remove_quick    ir_nodeset_remove_quick
+#define hashset_fixup           ir_nodeset_fixup
+#include "arrayset.c"
+
+#else
+
 #include "hashset.c"
 
+#endif /* IR_NODESET_USE_ORDERED_SETS */
+
 void ir_nodeset_init(ir_nodeset_t *nodeset)
 {
        ir_nodeset_init_size(nodeset, 16);
@@ -66,5 +78,5 @@ void ir_nodeset_init(ir_nodeset_t *nodeset)
 
 int ir_nodeset_contains(const ir_nodeset_t *this, const ir_node *node)
 {
-       return _ir_nodeset_find(this, node);
+       return _ir_nodeset_find(this, node) != NULL;
 }
index 56a7df8..d60bf5f 100644 (file)
 #include "firm_types.h"
 #include "xmalloc.h"
 
+/*
+ * sebastian experimental:
+ * use ordered arrays as node sets.
+ * the guys here have made good experiences with that.
+ * Internally we use normal Firm arrays and binary
+ * search for locating the elements. Using arrays should
+ * give the sets a small footprint.
+ */
+#undef  IR_NODESET_USE_ORDERED_SETS
+
 #define HashSet          ir_nodeset_t
 #define HashSetIterator  ir_nodeset_iterator_t
 #define ValueType        ir_node*
 #define DO_REHASH
+
+#ifdef IR_NODESET_USE_ORDERED_SETS
+#include "arrayset.h"
+#else
 #include "hashset.h"
+#endif
+
 #undef DO_REHASH
 #undef ValueType
 #undef HashSetIterator
@@ -99,6 +115,7 @@ static INLINE void ir_nodeset_del(ir_nodeset_t *nodeset) {
  */
 int ir_nodeset_insert(ir_nodeset_t *nodeset, ir_node *node);
 
+
 /**
  * Removes a node from a nodeset. Does nothing if the nodeset doesn't contain
  * the node.
@@ -160,4 +177,46 @@ void ir_nodeset_remove_iterator(ir_nodeset_t *nodeset,
         irn = ir_nodeset_iterator_next(&iter);    \
                irn != NULL; irn = ir_nodeset_iterator_next(&iter))
 
+
+#ifdef IR_NODESET_USE_ORDERED_SETS
+
+/**
+ * Insert an element quickly into from the set.
+ * This method may destroy internal invariats of the set (think of sorted arrays).
+ * All calls to other routines but
+ * - iteration
+ * - get the number of elements in the set
+ * will not work until ir_nodeset_fixup() was called.
+ * @param nodeset The nodeset.
+ * @param node    The node to insert.
+ */
+void ir_nodeset_insert_quick(ir_nodeset_t *nodeset, ir_node *node);
+
+/**
+ * Remove an element quickly from the set.
+ * This method may destroy internal invariats of the set (think of sorted arrays).
+ * All calls to other routines but
+ * - iteration
+ * - get the number of elements in the set
+ * will not work until ir_nodeset_fixup() was called.
+ * @param nodeset The nodeset.
+ * @param node    The node to delete.
+ */
+void ir_nodeset_remove_quick(ir_nodeset_t *nodeset, const ir_node *node);
+
+/**
+ * Fixes up internal state of the set.
+ * Is needed when one of the _quick functions was called.
+ * @param nodeset The nodeset.
+ */
+void ir_nodeset_fixup(ir_nodeset_t *nodeset);
+
+#else
+
+#define ir_nodeset_remove_quick ir_nodeset_remove
+#define ir_nodeset_insert_quick ir_nodeset_insert
+#define ir_nodeset_fixup(set)
+
+#endif /* IR_NODESET_USE_ORDERED_SETS */
+
 #endif