c1_ValueMap.hpp revision 1879:f95d63e2154a
1164640Sflz/*
298186Sgordon * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
378344Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4157473Sflz *
578344Sobrien * This code is free software; you can redistribute it and/or modify it
678344Sobrien * under the terms of the GNU General Public License version 2 only, as
778344Sobrien * published by the Free Software Foundation.
878344Sobrien *
978344Sobrien * This code is distributed in the hope that it will be useful, but WITHOUT
1078344Sobrien * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1178344Sobrien * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1278344Sobrien * version 2 for more details (a copy is included in the LICENSE file that
1378344Sobrien * accompanied this code).
1478344Sobrien *
1578344Sobrien * You should have received a copy of the GNU General Public License version
1678344Sobrien * 2 along with this work; if not, write to the Free Software Foundation,
1778344Sobrien * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1878344Sobrien *
1978344Sobrien * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2078344Sobrien * or visit www.oracle.com if you need additional information or have any
2178344Sobrien * questions.
2278344Sobrien *
2378344Sobrien */
2478344Sobrien
2578344Sobrien#ifndef SHARE_VM_C1_C1_VALUEMAP_HPP
2678344Sobrien#define SHARE_VM_C1_C1_VALUEMAP_HPP
2778344Sobrien
2878344Sobrien#include "c1/c1_Instruction.hpp"
2978344Sobrien#include "c1/c1_ValueSet.hpp"
3078344Sobrien#include "memory/allocation.hpp"
3178344Sobrien
3278344Sobrienclass ValueMapEntry: public CompilationResourceObj {
3378344Sobrien private:
3478344Sobrien  intx           _hash;
35157473Sflz  Value          _value;
36169668Smtm  int            _nesting;
37157473Sflz  ValueMapEntry* _next;
3878344Sobrien
3998186Sgordon public:
4098186Sgordon  ValueMapEntry(intx hash, Value value, int nesting, ValueMapEntry* next)
4198186Sgordon    : _hash(hash)
42131550Scperciva    , _value(value)
43131550Scperciva    , _nesting(nesting)
44131550Scperciva    , _next(next)
45131550Scperciva  {
4698186Sgordon  }
4798186Sgordon
48202988Semaste  intx           hash()      { return _hash; }
49124832Smtm  Value          value()     { return _value; }
50124832Smtm  int            nesting()   { return _nesting; }
51161435Syar  ValueMapEntry* next()      { return _next; }
52161435Syar
5398186Sgordon  void set_next(ValueMapEntry* next) { _next = next; }
5498186Sgordon};
5578344Sobrien
5678344Sobriendefine_array(ValueMapEntryArray, ValueMapEntry*)
5778344Sobriendefine_stack(ValueMapEntryList, ValueMapEntryArray)
58197144Shrs
5978344Sobrien// ValueMap implements nested hash tables for value numbering.  It
60197144Shrs// maintains a set _killed_values which represents the instructions
61197144Shrs// which have been killed so far and an array of linked lists of
6298186Sgordon// ValueMapEntries names _entries.  Each ValueMapEntry has a nesting
63197144Shrs// which indicates what ValueMap nesting it belongs to.  Higher
64197144Shrs// nesting values are always before lower values in the linked list.
65197144Shrs// This allows cloning of parent ValueMaps by simply copying the heads
66197144Shrs// of the list.  _entry_count represents the number of reachable
67197144Shrs// entries in the ValueMap.  A ValueMap is only allowed to mutate
68197144Shrs// ValueMapEntries with the same nesting level.  Adding or removing
69197144Shrs// entries at the current nesting level requires updating
70197144Shrs// _entry_count.  Elements in the parent's list that get killed can be
71197144Shrs// skipped if they are at the head of the list by simply moving to the
7298186Sgordon// next element in the list and decrementing _entry_count.
7398186Sgordon
74197144Shrsclass ValueMap: public CompilationResourceObj {
75197144Shrs private:
76197144Shrs  int           _nesting;
7798186Sgordon  ValueMapEntryArray _entries;
78197144Shrs  ValueSet      _killed_values;
79197144Shrs  int           _entry_count;
8098186Sgordon
8198186Sgordon  int           nesting()                        { return _nesting; }
82197144Shrs  bool          is_local_value_numbering()       { return _nesting == 0; }
83197144Shrs  bool          is_global_value_numbering()      { return _nesting > 0; }
84197144Shrs
85197144Shrs  int           entry_count()                    { return _entry_count; }
86197144Shrs  int           size()                           { return _entries.length(); }
87197144Shrs  ValueMapEntry* entry_at(int i)                 { return _entries.at(i); }
88197144Shrs
89197144Shrs  // calculates the index of a hash value in a hash table of size n
90197144Shrs  int           entry_index(intx hash, int n)    { return (unsigned int)hash % n; }
91197144Shrs
92197144Shrs  // if entry_count > size_threshold, the size of the hash table is increased
93197144Shrs  int           size_threshold()                 { return size(); }
94197144Shrs
9598186Sgordon  // management of the killed-bitset for global value numbering
9698186Sgordon  void          kill_value(Value v)              { if (is_global_value_numbering()) _killed_values.put(v); }
9798186Sgordon  bool          is_killed(Value v)               { if (is_global_value_numbering()) return _killed_values.contains(v); else return false; }
9898186Sgordon
99197144Shrs  // helper functions
100197144Shrs  void          increase_table_size();
101197144Shrs
10298186Sgordon#ifndef PRODUCT
103197144Shrs  static int _number_of_finds;
104197144Shrs  static int _number_of_hits;
105197144Shrs  static int _number_of_kills;
106197144Shrs#endif // PRODUCT
107197144Shrs
108197144Shrs public:
109197144Shrs  // creation
110197144Shrs  ValueMap();                // empty value map
111197144Shrs  ValueMap(ValueMap* old);   // value map with increased nesting
112197144Shrs
113197144Shrs  // manipulation
114197144Shrs  Value find_insert(Value x);
115197144Shrs
11698186Sgordon  void kill_memory();
11798186Sgordon  void kill_field(ciField* field);
11898186Sgordon  void kill_array(ValueType* type);
11998186Sgordon  void kill_exception();
12098186Sgordon  void kill_map(ValueMap* map);
12198186Sgordon  void kill_all();
12298186Sgordon
12398186Sgordon#ifndef PRODUCT
12498186Sgordon  // debugging/printing
12598186Sgordon  void print();
12698186Sgordon
127146490Sschweikh  static void reset_statistics();
12898186Sgordon  static void print_statistics();
12998186Sgordon#endif
13098186Sgordon};
13198186Sgordon
13298186Sgordondefine_array(ValueMapArray, ValueMap*)
13398186Sgordon
13498186Sgordon
13578344Sobrienclass ValueNumberingVisitor: public InstructionVisitor {
13678344Sobrien protected:
13778344Sobrien  // called by visitor functions for instructions that kill values
13878344Sobrien  virtual void kill_memory() = 0;
13978344Sobrien  virtual void kill_field(ciField* field) = 0;
14078344Sobrien  virtual void kill_array(ValueType* type) = 0;
14178344Sobrien
14298186Sgordon  // visitor functions
14378344Sobrien  void do_StoreField     (StoreField*      x) {
14478344Sobrien    if (!x->is_initialized()) {
14578344Sobrien      kill_memory();
14678344Sobrien    } else {
14778344Sobrien      kill_field(x->field());
14878344Sobrien    }
14978344Sobrien  }
15078344Sobrien  void do_StoreIndexed   (StoreIndexed*    x) { kill_array(x->type()); }
15178344Sobrien  void do_MonitorEnter   (MonitorEnter*    x) { kill_memory(); }
15278344Sobrien  void do_MonitorExit    (MonitorExit*     x) { kill_memory(); }
15378344Sobrien  void do_Invoke         (Invoke*          x) { kill_memory(); }
15478344Sobrien  void do_UnsafePutRaw   (UnsafePutRaw*    x) { kill_memory(); }
155157473Sflz  void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); }
15678344Sobrien  void do_Intrinsic      (Intrinsic*       x) { if (!x->preserves_state()) kill_memory(); }
15778344Sobrien
15878344Sobrien  void do_Phi            (Phi*             x) { /* nothing to do */ }
15978344Sobrien  void do_Local          (Local*           x) { /* nothing to do */ }
16078344Sobrien  void do_Constant       (Constant*        x) { /* nothing to do */ }
161157473Sflz  void do_LoadField      (LoadField*       x) {
16298186Sgordon    if (!x->is_initialized()) {
16398186Sgordon      kill_memory();
16478344Sobrien    }
16598186Sgordon  }
16698186Sgordon  void do_ArrayLength    (ArrayLength*     x) { /* nothing to do */ }
16798186Sgordon  void do_LoadIndexed    (LoadIndexed*     x) { /* nothing to do */ }
168126286Smtm  void do_NegateOp       (NegateOp*        x) { /* nothing to do */ }
16998186Sgordon  void do_ArithmeticOp   (ArithmeticOp*    x) { /* nothing to do */ }
17098186Sgordon  void do_ShiftOp        (ShiftOp*         x) { /* nothing to do */ }
17198186Sgordon  void do_LogicOp        (LogicOp*         x) { /* nothing to do */ }
17298186Sgordon  void do_CompareOp      (CompareOp*       x) { /* nothing to do */ }
17398186Sgordon  void do_IfOp           (IfOp*            x) { /* nothing to do */ }
174169668Smtm  void do_Convert        (Convert*         x) { /* nothing to do */ }
175169668Smtm  void do_NullCheck      (NullCheck*       x) { /* nothing to do */ }
176169668Smtm  void do_NewInstance    (NewInstance*     x) { /* nothing to do */ }
177169668Smtm  void do_NewTypeArray   (NewTypeArray*    x) { /* nothing to do */ }
17878344Sobrien  void do_NewObjectArray (NewObjectArray*  x) { /* nothing to do */ }
179169668Smtm  void do_NewMultiArray  (NewMultiArray*   x) { /* nothing to do */ }
180169668Smtm  void do_CheckCast      (CheckCast*       x) { /* nothing to do */ }
181169668Smtm  void do_InstanceOf     (InstanceOf*      x) { /* nothing to do */ }
182169668Smtm  void do_BlockBegin     (BlockBegin*      x) { /* nothing to do */ }
183178776Smaxim  void do_Goto           (Goto*            x) { /* nothing to do */ }
184178776Smaxim  void do_If             (If*              x) { /* nothing to do */ }
185178770Smtm  void do_IfInstanceOf   (IfInstanceOf*    x) { /* nothing to do */ }
186169668Smtm  void do_TableSwitch    (TableSwitch*     x) { /* nothing to do */ }
187178770Smtm  void do_LookupSwitch   (LookupSwitch*    x) { /* nothing to do */ }
188178770Smtm  void do_Return         (Return*          x) { /* nothing to do */ }
189169668Smtm  void do_Throw          (Throw*           x) { /* nothing to do */ }
190178770Smtm  void do_Base           (Base*            x) { /* nothing to do */ }
191178775Smaxim  void do_OsrEntry       (OsrEntry*        x) { /* nothing to do */ }
192169668Smtm  void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ }
193169668Smtm  void do_RoundFP        (RoundFP*         x) { /* nothing to do */ }
194169668Smtm  void do_UnsafeGetRaw   (UnsafeGetRaw*    x) { /* nothing to do */ }
195169668Smtm  void do_ProfileInvoke  (ProfileInvoke*   x) { /* nothing to do */ };
196169668Smtm  void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ }
197169668Smtm  void do_UnsafePrefetchRead (UnsafePrefetchRead*  x) { /* nothing to do */ }
198169668Smtm  void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ }
199169668Smtm  void do_ProfileCall    (ProfileCall*     x) { /* nothing to do */ }
20098186Sgordon};
20198186Sgordon
20298186Sgordon
20398186Sgordonclass ValueNumberingEffects: public ValueNumberingVisitor {
20498186Sgordon private:
20578344Sobrien  ValueMap*     _map;
20678344Sobrien
20798186Sgordon public:
20878344Sobrien  // implementation for abstract methods of ValueNumberingVisitor
20978344Sobrien  void          kill_memory()                    { _map->kill_memory(); }
210126285Smtm  void          kill_field(ciField* field)       { _map->kill_field(field); }
21178344Sobrien  void          kill_array(ValueType* type)      { _map->kill_array(type); }
21278344Sobrien
213126285Smtm  ValueNumberingEffects(ValueMap* map): _map(map) {}
21478344Sobrien};
21578344Sobrien
216126285Smtm
217126285Smtmclass GlobalValueNumbering: public ValueNumberingVisitor {
218126285Smtm private:
21978344Sobrien  ValueMap*     _current_map;     // value map of current block
22078344Sobrien  ValueMapArray _value_maps;      // list of value maps for all blocks
22198186Sgordon
22278344Sobrien public:
22378344Sobrien  // accessors
22478344Sobrien  ValueMap*     current_map()                    { return _current_map; }
22578344Sobrien  ValueMap*     value_map_of(BlockBegin* block)  { return _value_maps.at(block->linear_scan_number()); }
22698186Sgordon  void          set_value_map_of(BlockBegin* block, ValueMap* map)   { assert(value_map_of(block) == NULL, ""); _value_maps.at_put(block->linear_scan_number(), map); }
22798186Sgordon
22878344Sobrien  // implementation for abstract methods of ValueNumberingVisitor
22998186Sgordon  void          kill_memory()                    { current_map()->kill_memory(); }
23098186Sgordon  void          kill_field(ciField* field)       { current_map()->kill_field(field); }
23178344Sobrien  void          kill_array(ValueType* type)      { current_map()->kill_array(type); }
23278344Sobrien
23378344Sobrien  // main entry point that performs global value numbering
23478344Sobrien  GlobalValueNumbering(IR* ir);
23578344Sobrien};
23698186Sgordon
23778344Sobrien#endif // SHARE_VM_C1_C1_VALUEMAP_HPP
23898186Sgordon