ScopedHashTable.h revision d10e467ad961f7c3b548ee2f2de8a576a245e25a
1d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//===- ScopedHashTable.h - A simple scoped hash table ---------------------===//
2d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//
3d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//                     The LLVM Compiler Infrastructure
4d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//
5d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner// This file is distributed under the University of Illinois Open Source
6d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner// License. See LICENSE.TXT for details.
7d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//
8d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//===----------------------------------------------------------------------===//
9d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//
10d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner// This file implements an efficient scoped hash table, which is useful for
11d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner// things like dominator-based optimizations.  This allows clients to do things
12d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner// like this:
13d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//
14d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//  ScopedHashTable<int, int> HT;
15d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//  {
16d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//    ScopedHashTableScope<int, int> Scope1(HT);
17d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//    HT.insert(0, 0);
18d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//    HT.insert(1, 1);
19d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//    {
20d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//      ScopedHashTableScope<int, int> Scope2(HT);
21d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//      HT.insert(0, 42);
22d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//    }
23d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//  }
24d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//
25d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner// Looking up the value for "0" in the Scope2 block will return 42.  Looking
26d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner// up the value for 0 before 42 is inserted or after Scope2 is popped will
27d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner// return 0.
28d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//
29d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner//===----------------------------------------------------------------------===//
30d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
31d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner#ifndef LLVM_ADT_SCOPEDHASHTABLE_H
32d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner#define LLVM_ADT_SCOPEDHASHTABLE_H
33d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
34d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner#include <cassert>
35d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner#include "llvm/ADT/DenseMap.h"
36d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
37d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnernamespace llvm {
38d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
39d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnertemplate <typename K, typename V>
40d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnerclass ScopedHashTable;
41d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
42d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnertemplate <typename K, typename V>
43d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnerclass ScopedHashTableVal {
44d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableVal *NextInScope;
45d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableVal *NextForKey;
46d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  K Key;
47d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  V Val;
48d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnerpublic:
49d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableVal(ScopedHashTableVal *nextInScope,
50d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner                     ScopedHashTableVal *nextForKey, const K &key, const V &val)
51d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    : NextInScope(nextInScope), NextForKey(nextForKey), Key(key), Val(val) {
52d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  }
53d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
54d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  const K &getKey() const { return Key; }
55d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  const V &getValue() const { return Val; }
56d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  V &getValue() { return Val; }
57d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
58d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableVal *getNextForKey() { return NextForKey; }
59d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  const ScopedHashTableVal *getNextForKey() const { return NextForKey; }
60d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnerpublic:
61d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableVal *getNextInScope() { return NextInScope; }
62d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner};
63d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
64d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnertemplate <typename K, typename V>
65d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnerclass ScopedHashTableScope {
66d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  /// HT - The hashtable that we are active for.
67d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTable<K, V> &HT;
68d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
69d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  /// PrevScope - This is the scope that we are shadowing in HT.
70d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableScope *PrevScope;
71d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
72d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  /// LastValInScope - This is the last value that was inserted for this scope
73d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  /// or null if none have been inserted yet.
74d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableVal<K,V> *LastValInScope;
75d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  void operator=(ScopedHashTableScope&);       // DO NOT IMPLEMENT
76d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableScope(ScopedHashTableScope&); // DO NOT IMPLEMENT
77d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnerpublic:
78d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableScope(ScopedHashTable<K, V> &HT);
79d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ~ScopedHashTableScope();
80d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
81d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnerprivate:
82d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  friend class ScopedHashTable<K, V>;
83d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableVal<K, V> *getLastValInScope() { return LastValInScope; }
84d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  void setLastValInScope(ScopedHashTableVal<K,V> *Val) { LastValInScope = Val; }
85d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner};
86d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
87d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
88d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnertemplate <typename K, typename V>
89d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnerclass ScopedHashTableIterator {
90d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableVal<K,V> *Node;
91d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnerpublic:
92d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableIterator(ScopedHashTableVal<K,V> *node) : Node(node){}
93d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
94d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  V &operator*() const {
95d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    assert(Node && "Dereference end()");
96d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    return Node->getValue();
97d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  }
98d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  V *operator->() const {
99d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    return &Node->getValue();
100d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  }
101d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
102d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  bool operator==(const ScopedHashTableIterator &RHS) const {
103d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    return Node == RHS.Node;
104d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  }
105d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  bool operator!=(const ScopedHashTableIterator &RHS) const {
106d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    return Node != RHS.Node;
107d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  }
108d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
109d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  inline ScopedHashTableIterator& operator++() {          // Preincrement
110d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    assert(Node && "incrementing past end()");
111d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    Node = Node->getNextForKey();
112d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    return *this;
113d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  }
114d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableIterator operator++(int) {        // Postincrement
115d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    ScopedHashTableIterator tmp = *this; ++*this; return tmp;
116d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  }
117d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner};
118d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
119d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
120d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnertemplate <typename K, typename V>
121d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnerclass ScopedHashTable {
122d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  DenseMap<K, ScopedHashTableVal<K,V>*> TopLevelMap;
123d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTableScope<K, V> *CurScope;
124d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTable(const ScopedHashTable&); // NOT YET IMPLEMENTED
125d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  void operator=(const ScopedHashTable&);  // NOT YET IMPLEMENTED
126d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  friend class ScopedHashTableScope<K, V>;
127d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnerpublic:
128d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ScopedHashTable() : CurScope(0) {}
129d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  ~ScopedHashTable() {
130d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!");
131d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  }
132d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
133d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  void insert(const K &Key, const V &Val) {
134d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    assert(CurScope && "No scope active!");
135d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
136d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    ScopedHashTableVal<K,V> *&KeyEntry = TopLevelMap[Key];
137d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
138d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    KeyEntry = new ScopedHashTableVal<K,V>(CurScope->getLastValInScope(),
139d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner                                           KeyEntry, Key, Val);
140d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    CurScope->setLastValInScope(KeyEntry);
141d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  }
142d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
143d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  typedef ScopedHashTableIterator<K, V> iterator;
144d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
145d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  iterator end() { return iterator(0); }
146d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
147d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  iterator begin(const K &Key) {
148d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    typename DenseMap<K, ScopedHashTableVal<K,V>*>::iterator I =
149d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner      TopLevelMap.find(Key);
150d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    if (I == TopLevelMap.end()) return end();
151d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    return iterator(I->second);
152d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  }
153d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner};
154d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
155d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner/// ScopedHashTableScope ctor - Install this as the current scope for the hash
156d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner/// table.
157d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnertemplate <typename K, typename V>
158d10e467ad961f7c3b548ee2f2de8a576a245e25aChris LattnerScopedHashTableScope<K, V>::ScopedHashTableScope(ScopedHashTable<K, V> &ht)
159d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  : HT(ht) {
160d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  PrevScope = HT.CurScope;
161d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  HT.CurScope = this;
162d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  LastValInScope = 0;
163d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner}
164d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
165d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattnertemplate <typename K, typename V>
166d10e467ad961f7c3b548ee2f2de8a576a245e25aChris LattnerScopedHashTableScope<K, V>::~ScopedHashTableScope() {
167d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  assert(HT.CurScope == this && "Scope imbalance!");
168d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  HT.CurScope = PrevScope;
169d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
170d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  // Pop and delete all values corresponding to this scope.
171d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  while (ScopedHashTableVal<K, V> *ThisEntry = LastValInScope) {
172d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    // Pop this value out of the TopLevelMap.
173d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    if (ThisEntry->getNextForKey() == 0) {
174d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner      assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry &&
175d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner             "Scope imbalance!");
176d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner      HT.TopLevelMap.erase(ThisEntry->getKey());
177d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    } else {
178d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner      ScopedHashTableVal<K,V> *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()];
179d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner      assert(KeyEntry == ThisEntry && "Scope imbalance!");
180d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner      KeyEntry = ThisEntry->getNextForKey();
181d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    }
182d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
183d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    // Pop this value out of the scope.
184d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    LastValInScope = ThisEntry->getNextInScope();
185d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
186d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    // Delete this entry.
187d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner    delete ThisEntry;
188d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner  }
189d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner}
190d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
191d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner} // end namespace llvm
192d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner
193d10e467ad961f7c3b548ee2f2de8a576a245e25aChris Lattner#endif
194