c1_ValueMap.hpp revision 470:ad8c8ca4ab0f
1/*
2 * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25class ValueMapEntry: public CompilationResourceObj {
26 private:
27  intx           _hash;
28  Value          _value;
29  int            _nesting;
30  ValueMapEntry* _next;
31
32 public:
33  ValueMapEntry(intx hash, Value value, int nesting, ValueMapEntry* next)
34    : _hash(hash)
35    , _value(value)
36    , _nesting(nesting)
37    , _next(next)
38  {
39  }
40
41  intx           hash()      { return _hash; }
42  Value          value()     { return _value; }
43  int            nesting()   { return _nesting; }
44  ValueMapEntry* next()      { return _next; }
45
46  void set_next(ValueMapEntry* next) { _next = next; }
47};
48
49define_array(ValueMapEntryArray, ValueMapEntry*)
50define_stack(ValueMapEntryList, ValueMapEntryArray)
51
52// ValueMap implements nested hash tables for value numbering.  It
53// maintains a set _killed_values which represents the instructions
54// which have been killed so far and an array of linked lists of
55// ValueMapEntries names _entries.  Each ValueMapEntry has a nesting
56// which indicates what ValueMap nesting it belongs to.  Higher
57// nesting values are always before lower values in the linked list.
58// This allows cloning of parent ValueMaps by simply copying the heads
59// of the list.  _entry_count represents the number of reachable
60// entries in the ValueMap.  A ValueMap is only allowed to mutate
61// ValueMapEntries with the same nesting level.  Adding or removing
62// entries at the current nesting level requires updating
63// _entry_count.  Elements in the parent's list that get killed can be
64// skipped if they are at the head of the list by simply moving to the
65// next element in the list and decrementing _entry_count.
66
67class ValueMap: public CompilationResourceObj {
68 private:
69  int           _nesting;
70  ValueMapEntryArray _entries;
71  ValueSet      _killed_values;
72  int           _entry_count;
73
74  int           nesting()                        { return _nesting; }
75  bool          is_local_value_numbering()       { return _nesting == 0; }
76  bool          is_global_value_numbering()      { return _nesting > 0; }
77
78  int           entry_count()                    { return _entry_count; }
79  int           size()                           { return _entries.length(); }
80  ValueMapEntry* entry_at(int i)                 { return _entries.at(i); }
81
82  // calculates the index of a hash value in a hash table of size n
83  int           entry_index(intx hash, int n)    { return (unsigned int)hash % n; }
84
85  // if entry_count > size_threshold, the size of the hash table is increased
86  int           size_threshold()                 { return size(); }
87
88  // management of the killed-bitset for global value numbering
89  void          kill_value(Value v)              { if (is_global_value_numbering()) _killed_values.put(v); }
90  bool          is_killed(Value v)               { if (is_global_value_numbering()) return _killed_values.contains(v); else return false; }
91
92  // helper functions
93  void          increase_table_size();
94
95#ifndef PRODUCT
96  static int _number_of_finds;
97  static int _number_of_hits;
98  static int _number_of_kills;
99#endif // PRODUCT
100
101 public:
102  // creation
103  ValueMap();                // empty value map
104  ValueMap(ValueMap* old);   // value map with increased nesting
105
106  // manipulation
107  Value find_insert(Value x);
108
109  void kill_memory();
110  void kill_field(ciField* field);
111  void kill_array(ValueType* type);
112  void kill_exception();
113  void kill_map(ValueMap* map);
114  void kill_all();
115
116#ifndef PRODUCT
117  // debugging/printing
118  void print();
119
120  static void reset_statistics();
121  static void print_statistics();
122#endif
123};
124
125define_array(ValueMapArray, ValueMap*)
126
127
128class ValueNumberingVisitor: public InstructionVisitor {
129 protected:
130  // called by visitor functions for instructions that kill values
131  virtual void kill_memory() = 0;
132  virtual void kill_field(ciField* field) = 0;
133  virtual void kill_array(ValueType* type) = 0;
134
135  // visitor functions
136  void do_StoreField     (StoreField*      x) {
137    if (!x->is_initialized()) {
138      kill_memory();
139    } else {
140      kill_field(x->field());
141    }
142  }
143  void do_StoreIndexed   (StoreIndexed*    x) { kill_array(x->type()); }
144  void do_MonitorEnter   (MonitorEnter*    x) { kill_memory(); }
145  void do_MonitorExit    (MonitorExit*     x) { kill_memory(); }
146  void do_Invoke         (Invoke*          x) { kill_memory(); }
147  void do_UnsafePutRaw   (UnsafePutRaw*    x) { kill_memory(); }
148  void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); }
149  void do_Intrinsic      (Intrinsic*       x) { if (!x->preserves_state()) kill_memory(); }
150
151  void do_Phi            (Phi*             x) { /* nothing to do */ }
152  void do_Local          (Local*           x) { /* nothing to do */ }
153  void do_Constant       (Constant*        x) { /* nothing to do */ }
154  void do_LoadField      (LoadField*       x) {
155    if (!x->is_initialized()) {
156      kill_memory();
157    }
158  }
159  void do_ArrayLength    (ArrayLength*     x) { /* nothing to do */ }
160  void do_LoadIndexed    (LoadIndexed*     x) { /* nothing to do */ }
161  void do_NegateOp       (NegateOp*        x) { /* nothing to do */ }
162  void do_ArithmeticOp   (ArithmeticOp*    x) { /* nothing to do */ }
163  void do_ShiftOp        (ShiftOp*         x) { /* nothing to do */ }
164  void do_LogicOp        (LogicOp*         x) { /* nothing to do */ }
165  void do_CompareOp      (CompareOp*       x) { /* nothing to do */ }
166  void do_IfOp           (IfOp*            x) { /* nothing to do */ }
167  void do_Convert        (Convert*         x) { /* nothing to do */ }
168  void do_NullCheck      (NullCheck*       x) { /* nothing to do */ }
169  void do_NewInstance    (NewInstance*     x) { /* nothing to do */ }
170  void do_NewTypeArray   (NewTypeArray*    x) { /* nothing to do */ }
171  void do_NewObjectArray (NewObjectArray*  x) { /* nothing to do */ }
172  void do_NewMultiArray  (NewMultiArray*   x) { /* nothing to do */ }
173  void do_CheckCast      (CheckCast*       x) { /* nothing to do */ }
174  void do_InstanceOf     (InstanceOf*      x) { /* nothing to do */ }
175  void do_BlockBegin     (BlockBegin*      x) { /* nothing to do */ }
176  void do_Goto           (Goto*            x) { /* nothing to do */ }
177  void do_If             (If*              x) { /* nothing to do */ }
178  void do_IfInstanceOf   (IfInstanceOf*    x) { /* nothing to do */ }
179  void do_TableSwitch    (TableSwitch*     x) { /* nothing to do */ }
180  void do_LookupSwitch   (LookupSwitch*    x) { /* nothing to do */ }
181  void do_Return         (Return*          x) { /* nothing to do */ }
182  void do_Throw          (Throw*           x) { /* nothing to do */ }
183  void do_Base           (Base*            x) { /* nothing to do */ }
184  void do_OsrEntry       (OsrEntry*        x) { /* nothing to do */ }
185  void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ }
186  void do_RoundFP        (RoundFP*         x) { /* nothing to do */ }
187  void do_UnsafeGetRaw   (UnsafeGetRaw*    x) { /* nothing to do */ }
188  void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ }
189  void do_UnsafePrefetchRead (UnsafePrefetchRead*  x) { /* nothing to do */ }
190  void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ }
191  void do_ProfileCall    (ProfileCall*     x) { /* nothing to do */ }
192  void do_ProfileCounter (ProfileCounter*  x) { /* nothing to do */ }
193};
194
195
196class ValueNumberingEffects: public ValueNumberingVisitor {
197 private:
198  ValueMap*     _map;
199
200 public:
201  // implementation for abstract methods of ValueNumberingVisitor
202  void          kill_memory()                    { _map->kill_memory(); }
203  void          kill_field(ciField* field)       { _map->kill_field(field); }
204  void          kill_array(ValueType* type)      { _map->kill_array(type); }
205
206  ValueNumberingEffects(ValueMap* map): _map(map) {}
207};
208
209
210class GlobalValueNumbering: public ValueNumberingVisitor {
211 private:
212  ValueMap*     _current_map;     // value map of current block
213  ValueMapArray _value_maps;      // list of value maps for all blocks
214
215 public:
216  // accessors
217  ValueMap*     current_map()                    { return _current_map; }
218  ValueMap*     value_map_of(BlockBegin* block)  { return _value_maps.at(block->linear_scan_number()); }
219  void          set_value_map_of(BlockBegin* block, ValueMap* map)   { assert(value_map_of(block) == NULL, ""); _value_maps.at_put(block->linear_scan_number(), map); }
220
221  // implementation for abstract methods of ValueNumberingVisitor
222  void          kill_memory()                    { current_map()->kill_memory(); }
223  void          kill_field(ciField* field)       { current_map()->kill_field(field); }
224  void          kill_array(ValueType* type)      { current_map()->kill_array(type); }
225
226  // main entry point that performs global value numbering
227  GlobalValueNumbering(IR* ir);
228};
229