hotspot/src/share/vm/c1/c1_LinearScan.hpp
author iveresov
Thu, 02 Dec 2010 17:21:12 -0800
changeset 7432 f06f1253c317
parent 7397 5b173b4ca846
child 7705 50fdff25b18d
permissions -rw-r--r--
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer Summary: C1 with profiling doesn't check whether the MDO has been really allocated, which can silently fail if the perm gen is full. The solution is to check if the allocation failed and bailout out of inlining or compilation. Reviewed-by: kvn, never
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
7397
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
     2
 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
5547
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1217
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1217
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1217
diff changeset
    21
 * questions.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
7397
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    25
#ifndef SHARE_VM_C1_C1_LINEARSCAN_HPP
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    26
#define SHARE_VM_C1_C1_LINEARSCAN_HPP
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    27
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    28
#include "c1/c1_FpuStackSim.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    29
#include "c1/c1_FrameMap.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    30
#include "c1/c1_IR.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    31
#include "c1/c1_Instruction.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    32
#include "c1/c1_LIR.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    33
#include "c1/c1_LIRGenerator.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    34
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
class DebugInfoCache;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
class FpuStackAllocator;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
class IRScopeDebugInfo;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
class Interval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
class IntervalWalker;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
class LIRGenerator;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
class LinearScan;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
class MoveResolver;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
class Range;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
define_array(IntervalArray, Interval*)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
define_stack(IntervalList, IntervalArray)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
define_array(IntervalsArray, IntervalList*)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
define_stack(IntervalsList, IntervalsArray)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
define_array(OopMapArray, OopMap*)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
define_stack(OopMapList, OopMapArray)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
define_array(ScopeValueArray, ScopeValue*)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
define_array(LIR_OpListArray, LIR_OpList*);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
define_stack(LIR_OpListStack, LIR_OpListArray);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
enum IntervalUseKind {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
  // priority of use kinds must be ascending
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
  noUse = 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
  loopEndMarker = 1,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
  shouldHaveRegister = 2,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
  mustHaveRegister = 3,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
  firstValidKind = 1,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
  lastValidKind = 3
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
define_array(UseKindArray, IntervalUseKind)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
define_stack(UseKindStack, UseKindArray)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
enum IntervalKind {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
  fixedKind = 0,  // interval pre-colored by LIR_Generator
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
  anyKind   = 1,  // no register/memory allocated by LIR_Generator
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
  nofKinds,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
  firstKind = fixedKind
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
// during linear scan an interval is in one of four states in
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
enum IntervalState {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
  unhandledState = 0, // unhandled state (not processed yet)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
  activeState   = 1,  // life and is in a physical register
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
  inactiveState = 2,  // in a life time hole and is in a physical register
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
  handledState  = 3,  // spilled or not life again
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
  invalidState = -1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
enum IntervalSpillState {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
  noDefinitionFound,  // starting state of calculation: no definition found yet
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
  oneDefinitionFound, // one definition has already been found.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
                      // Note: two consecutive definitions are treated as one (e.g. consecutive move and add because of two-operand LIR form)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
                      // the position of this definition is stored in _definition_pos
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
  oneMoveInserted,    // one spill move has already been inserted.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
  storeAtDefinition,  // the interval should be stored immediately after its definition because otherwise
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
                      // there would be multiple redundant stores
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
  startInMemory,      // the interval starts in memory (e.g. method parameter), so a store is never necessary
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
  noOptimization      // the interval has more then one definition (e.g. resulting from phi moves), so stores to memory are not optimized
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
#define for_each_interval_kind(kind) \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
  for (IntervalKind kind = firstKind; kind < nofKinds; kind = (IntervalKind)(kind + 1))
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
#define for_each_visitor_mode(mode) \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
  for (LIR_OpVisitState::OprMode mode = LIR_OpVisitState::firstMode; mode < LIR_OpVisitState::numModes; mode = (LIR_OpVisitState::OprMode)(mode + 1))
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
class LinearScan : public CompilationResourceObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
  // declare classes used by LinearScan as friends because they
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
  // need a wide variety of functions declared here
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
  // Only the small interface to the rest of the compiler is public
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
  friend class Interval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
  friend class IntervalWalker;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
  friend class LinearScanWalker;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
  friend class FpuStackAllocator;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
  friend class MoveResolver;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
  friend class LinearScanStatistic;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
  friend class LinearScanTimers;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
  friend class RegisterVerifier;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
  enum {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
    any_reg = -1,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
    nof_cpu_regs = pd_nof_cpu_regs_linearscan,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
    nof_fpu_regs = pd_nof_fpu_regs_linearscan,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
    nof_xmm_regs = pd_nof_xmm_regs_linearscan,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
    nof_regs = nof_cpu_regs + nof_fpu_regs + nof_xmm_regs
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
  Compilation*              _compilation;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
  IR*                       _ir;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
  LIRGenerator*             _gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
  FrameMap*                 _frame_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
  BlockList                 _cached_blocks;     // cached list with all blocks in linear-scan order (only correct if original list keeps unchanged)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
  int                       _num_virtual_regs;  // number of virtual registers (without new registers introduced because of splitting intervals)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
  bool                      _has_fpu_registers; // true if this method uses any floating point registers (and so fpu stack allocation is necessary)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
  int                       _num_calls;         // total number of calls in this method
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
  int                       _max_spills;        // number of stack slots used for intervals allocated to memory
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
  int                       _unused_spill_slot; // unused spill slot for a single-word value because of alignment of a double-word value
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
  IntervalList              _intervals;         // mapping from register number to interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
  IntervalList*             _new_intervals_from_allocation; // list with all intervals created during allocation when an existing interval is split
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
  IntervalArray*            _sorted_intervals;  // intervals sorted by Interval::from()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
  LIR_OpArray               _lir_ops;           // mapping from LIR_Op id to LIR_Op node
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
  BlockBeginArray           _block_of_op;       // mapping from LIR_Op id to the BlockBegin containing this instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
  BitMap                    _has_info;          // bit set for each LIR_Op id that has a CodeEmitInfo
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
  BitMap                    _has_call;          // bit set for each LIR_Op id that destroys all caller save registers
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
  BitMap2D                  _interval_in_loop;  // bit set for each virtual register that is contained in each loop
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
  // cached debug info to prevent multiple creation of same object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
  // TODO: cached scope values for registers could be static
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
  ScopeValueArray           _scope_value_cache;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
  static ConstantOopWriteValue _oop_null_scope_value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
  static ConstantIntValue    _int_m1_scope_value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
  static ConstantIntValue    _int_0_scope_value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
  static ConstantIntValue    _int_1_scope_value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
  static ConstantIntValue    _int_2_scope_value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
  // accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
  IR*           ir() const                       { return _ir; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
  Compilation*  compilation() const              { return _compilation; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
  LIRGenerator* gen() const                      { return _gen; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
  FrameMap*     frame_map() const                { return _frame_map; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
  // unified bailout support
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
  void          bailout(const char* msg) const   { compilation()->bailout(msg); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
  bool          bailed_out() const               { return compilation()->bailed_out(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
  // access to block list (sorted in linear scan order)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
  int           block_count() const              { assert(_cached_blocks.length() == ir()->linear_scan_order()->length(), "invalid cached block list"); return _cached_blocks.length(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
  BlockBegin*   block_at(int idx) const          { assert(_cached_blocks.at(idx) == ir()->linear_scan_order()->at(idx), "invalid cached block list");   return _cached_blocks.at(idx); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
  int           num_virtual_regs() const         { return _num_virtual_regs; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
  // size of live_in and live_out sets of BasicBlocks (BitMap needs rounded size for iteration)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
  int           live_set_size() const            { return round_to(_num_virtual_regs, BitsPerWord); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
  bool          has_fpu_registers() const        { return _has_fpu_registers; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
  int           num_loops() const                { return ir()->num_loops(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
  bool          is_interval_in_loop(int interval, int loop) const { return _interval_in_loop.at(interval, loop); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
  // handling of fpu stack allocation (platform dependent, needed for debug information generation)
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
   190
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
  FpuStackAllocator* _fpu_stack_allocator;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
  bool use_fpu_stack_allocation() const          { return UseSSE < 2 && has_fpu_registers(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
  bool use_fpu_stack_allocation() const          { return false; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
  // access to interval list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
  int           interval_count() const           { return _intervals.length(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
  Interval*     interval_at(int reg_num) const   { return _intervals.at(reg_num); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
  IntervalList* new_intervals_from_allocation() const { return _new_intervals_from_allocation; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
  // access to LIR_Ops and Blocks indexed by op_id
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
  int          max_lir_op_id() const                { assert(_lir_ops.length() > 0, "no operations"); return (_lir_ops.length() - 1) << 1; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
  LIR_Op*      lir_op_with_id(int op_id) const      { assert(op_id >= 0 && op_id <= max_lir_op_id() && op_id % 2 == 0, "op_id out of range or not even"); return _lir_ops.at(op_id >> 1); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
  BlockBegin*  block_of_op_with_id(int op_id) const { assert(_block_of_op.length() > 0 && op_id >= 0 && op_id <= max_lir_op_id() + 1, "op_id out of range"); return _block_of_op.at(op_id >> 1); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
  bool is_block_begin(int op_id)                    { return op_id == 0 || block_of_op_with_id(op_id) != block_of_op_with_id(op_id - 1); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
  bool covers_block_begin(int op_id_1, int op_id_2) { return block_of_op_with_id(op_id_1) != block_of_op_with_id(op_id_2); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
  bool has_call(int op_id)                          { assert(op_id % 2 == 0, "must be even"); return _has_call.at(op_id >> 1); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
  bool has_info(int op_id)                          { assert(op_id % 2 == 0, "must be even"); return _has_info.at(op_id >> 1); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
  // functions for converting LIR-Operands to register numbers
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
  static bool is_valid_reg_num(int reg_num)         { return reg_num >= 0; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
  static int  reg_num(LIR_Opr opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
  static int  reg_numHi(LIR_Opr opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
  // functions for classification of intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
  static bool is_precolored_interval(const Interval* i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
  static bool is_virtual_interval(const Interval* i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
  static bool is_precolored_cpu_interval(const Interval* i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
  static bool is_virtual_cpu_interval(const Interval* i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
  static bool is_precolored_fpu_interval(const Interval* i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
  static bool is_virtual_fpu_interval(const Interval* i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
  static bool is_in_fpu_register(const Interval* i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
  static bool is_oop_interval(const Interval* i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
  // General helper functions
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
  int         allocate_spill_slot(bool double_word);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
  void        assign_spill_slot(Interval* it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
  void        propagate_spill_slots();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
  Interval*   create_interval(int reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
  void        append_interval(Interval* it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
  void        copy_register_flags(Interval* from, Interval* to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
  // platform dependent functions
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
  static bool is_processed_reg_num(int reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
  static int  num_physical_regs(BasicType type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
  static bool requires_adjacent_regs(BasicType type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
  static bool is_caller_save(int assigned_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
  // spill move optimization: eliminate moves from register to stack if
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
  // stack slot is known to be correct
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
  void        change_spill_definition_pos(Interval* interval, int def_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
  void        change_spill_state(Interval* interval, int spill_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
  static bool must_store_at_definition(const Interval* i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
  void        eliminate_spill_moves();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
  // Phase 1: number all instructions in all blocks
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
  void number_instructions();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
  // Phase 2: compute local live sets separately for each block
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
  // (sets live_gen and live_kill for each block)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
  // helper methods used by compute_local_live_sets()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
  void set_live_gen_kill(Value value, LIR_Op* op, BitMap& live_gen, BitMap& live_kill);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
  void compute_local_live_sets();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
  // Phase 3: perform a backward dataflow analysis to compute global live sets
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
  // (sets live_in and live_out for each block)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
  void compute_global_live_sets();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
  // Phase 4: build intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
  // (fills the list _intervals)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
  // helper methods used by build_intervals()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
  void add_use (Value value, int from, int to, IntervalUseKind use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
  void add_def (LIR_Opr opr, int def_pos,      IntervalUseKind use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
  void add_use (LIR_Opr opr, int from, int to, IntervalUseKind use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
  void add_temp(LIR_Opr opr, int temp_pos,     IntervalUseKind use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
  void add_def (int reg_num, int def_pos,      IntervalUseKind use_kind, BasicType type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
  void add_use (int reg_num, int from, int to, IntervalUseKind use_kind, BasicType type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
  void add_temp(int reg_num, int temp_pos,     IntervalUseKind use_kind, BasicType type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
  // Add platform dependent kills for particular LIR ops.  Can be used
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
  // to add platform dependent behaviour for some operations.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
  void pd_add_temps(LIR_Op* op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
  IntervalUseKind use_kind_of_output_operand(LIR_Op* op, LIR_Opr opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
  IntervalUseKind use_kind_of_input_operand(LIR_Op* op, LIR_Opr opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
  void handle_method_arguments(LIR_Op* op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
  void handle_doubleword_moves(LIR_Op* op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
  void add_register_hints(LIR_Op* op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
  void build_intervals();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
  // Phase 5: actual register allocation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
  // (Uses LinearScanWalker)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
  // helper functions for building a sorted list of intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
  NOT_PRODUCT(bool is_sorted(IntervalArray* intervals);)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
  static int interval_cmp(Interval** a, Interval** b);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
  void add_to_list(Interval** first, Interval** prev, Interval* interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
  void create_unhandled_lists(Interval** list1, Interval** list2, bool (is_list1)(const Interval* i), bool (is_list2)(const Interval* i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
  void sort_intervals_before_allocation();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
  void sort_intervals_after_allocation();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
  void allocate_registers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
  // Phase 6: resolve data flow
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
  // (insert moves at edges between blocks if intervals have been split)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
  // helper functions for resolve_data_flow()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
  Interval* split_child_at_op_id(Interval* interval, int op_id, LIR_OpVisitState::OprMode mode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
  Interval* interval_at_block_begin(BlockBegin* block, int reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
  Interval* interval_at_block_end(BlockBegin* block, int reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
  Interval* interval_at_op_id(int reg_num, int op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
  void resolve_collect_mappings(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
  void resolve_find_insert_pos(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
  void resolve_data_flow();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
  void resolve_exception_entry(BlockBegin* block, int reg_num, MoveResolver &move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
  void resolve_exception_entry(BlockBegin* block, MoveResolver &move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
  void resolve_exception_edge(XHandler* handler, int throwing_op_id, int reg_num, Phi* phi, MoveResolver &move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
  void resolve_exception_edge(XHandler* handler, int throwing_op_id, MoveResolver &move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
  void resolve_exception_handlers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
  // Phase 7: assign register numbers back to LIR
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
  // (includes computation of debug information and oop maps)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
  // helper functions for assign_reg_num()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
  VMReg vm_reg_for_interval(Interval* interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
  VMReg vm_reg_for_operand(LIR_Opr opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
  static LIR_Opr operand_for_interval(Interval* interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
  static LIR_Opr calc_operand_for_interval(const Interval* interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
  LIR_Opr       canonical_spill_opr(Interval* interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
  LIR_Opr color_lir_opr(LIR_Opr opr, int id, LIR_OpVisitState::OprMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
  // methods used for oop map computation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
  IntervalWalker* init_compute_oop_maps();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
  OopMap*         compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo* info, bool is_call_site);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
  void            compute_oop_map(IntervalWalker* iw, const LIR_OpVisitState &visitor, LIR_Op* op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
  // methods used for debug information computation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
  void init_compute_debug_info();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
  MonitorValue*  location_for_monitor_index(int monitor_index);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
  LocationValue* location_for_name(int name, Location::Type loc_type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
  int append_scope_value_for_constant(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
  int append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
  int append_scope_value(int op_id, Value value, GrowableArray<ScopeValue*>* scope_values);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 5707
diff changeset
   359
  IRScopeDebugInfo* compute_debug_info_for_scope(int op_id, IRScope* cur_scope, ValueStack* cur_state, ValueStack* innermost_state);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
  void compute_debug_info(CodeEmitInfo* info, int op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
  void assign_reg_num(LIR_OpList* instructions, IntervalWalker* iw);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
  void assign_reg_num();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
  // Phase 8: fpu stack allocation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
  // (Used only on x86 when fpu operands are present)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
  void allocate_fpu_stack();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
  // helper functions for printing state
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
  static void print_bitmap(BitMap& bitmap);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
  void        print_intervals(const char* label);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
  void        print_lir(int level, const char* label, bool hir_valid = true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
  // verification functions for allocation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
  // (check that all intervals have a correct register and that no registers are overwritten)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
  void verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
  void verify_intervals();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
  void verify_no_oops_in_fixed_intervals();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
  void verify_constants();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
  void verify_registers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
489c9b5090e2 Initial load
duke
parents:
diff changeset
   388
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   389
  // creation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   390
  LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   391
489c9b5090e2 Initial load
duke
parents:
diff changeset
   392
  // main entry function: perform linear scan register allocation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
  void             do_linear_scan();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
  // accessors used by Compilation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
  int         max_spills()  const { return _max_spills; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
  int         num_calls() const   { assert(_num_calls >= 0, "not set"); return _num_calls; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
  // entry functions for printing
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
  static void print_statistics();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
  static void print_timers(double total);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   403
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   404
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   405
489c9b5090e2 Initial load
duke
parents:
diff changeset
   406
489c9b5090e2 Initial load
duke
parents:
diff changeset
   407
// Helper class for ordering moves that are inserted at the same position in the LIR
489c9b5090e2 Initial load
duke
parents:
diff changeset
   408
// When moves between registers are inserted, it is important that the moves are
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
// ordered such that no register is overwritten. So moves from register to stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
   410
// are processed prior to moves from stack to register. When moves have circular
489c9b5090e2 Initial load
duke
parents:
diff changeset
   411
// dependencies, a temporary stack slot is used to break the circle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   412
// The same logic is used in the LinearScanWalker and in LinearScan during resolve_data_flow
489c9b5090e2 Initial load
duke
parents:
diff changeset
   413
// and therefore factored out in a separate class
489c9b5090e2 Initial load
duke
parents:
diff changeset
   414
class MoveResolver: public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   415
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   416
  LinearScan*      _allocator;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   417
489c9b5090e2 Initial load
duke
parents:
diff changeset
   418
  LIR_List*        _insert_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   419
  int              _insert_idx;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   420
  LIR_InsertionBuffer _insertion_buffer; // buffer where moves are inserted
489c9b5090e2 Initial load
duke
parents:
diff changeset
   421
489c9b5090e2 Initial load
duke
parents:
diff changeset
   422
  IntervalList     _mapping_from;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   423
  LIR_OprList      _mapping_from_opr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   424
  IntervalList     _mapping_to;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   425
  bool             _multiple_reads_allowed;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   426
  int              _register_blocked[LinearScan::nof_regs];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   427
489c9b5090e2 Initial load
duke
parents:
diff changeset
   428
  int  register_blocked(int reg)                    { assert(reg >= 0 && reg < LinearScan::nof_regs, "out of bounds"); return _register_blocked[reg]; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   429
  void set_register_blocked(int reg, int direction) { assert(reg >= 0 && reg < LinearScan::nof_regs, "out of bounds"); assert(direction == 1 || direction == -1, "out of bounds"); _register_blocked[reg] += direction; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   430
489c9b5090e2 Initial load
duke
parents:
diff changeset
   431
  void block_registers(Interval* it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   432
  void unblock_registers(Interval* it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   433
  bool save_to_process_move(Interval* from, Interval* to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   434
489c9b5090e2 Initial load
duke
parents:
diff changeset
   435
  void create_insertion_buffer(LIR_List* list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   436
  void append_insertion_buffer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   437
  void insert_move(Interval* from_interval, Interval* to_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   438
  void insert_move(LIR_Opr from_opr, Interval* to_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   439
489c9b5090e2 Initial load
duke
parents:
diff changeset
   440
  DEBUG_ONLY(void verify_before_resolve();)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   441
  void resolve_mappings();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   442
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   443
  MoveResolver(LinearScan* allocator);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   444
489c9b5090e2 Initial load
duke
parents:
diff changeset
   445
  DEBUG_ONLY(void check_empty();)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   446
  void set_multiple_reads_allowed() { _multiple_reads_allowed = true; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   447
  void set_insert_position(LIR_List* insert_list, int insert_idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   448
  void move_insert_position(LIR_List* insert_list, int insert_idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   449
  void add_mapping(Interval* from, Interval* to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   450
  void add_mapping(LIR_Opr from, Interval* to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   451
  void resolve_and_append_moves();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   452
489c9b5090e2 Initial load
duke
parents:
diff changeset
   453
  LinearScan* allocator()   { return _allocator; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   454
  bool has_mappings()       { return _mapping_from.length() > 0; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   455
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   456
489c9b5090e2 Initial load
duke
parents:
diff changeset
   457
489c9b5090e2 Initial load
duke
parents:
diff changeset
   458
class Range : public CompilationResourceObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   459
  friend class Interval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   460
489c9b5090e2 Initial load
duke
parents:
diff changeset
   461
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   462
  static Range*    _end;       // sentinel (from == to == max_jint)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   463
489c9b5090e2 Initial load
duke
parents:
diff changeset
   464
  int              _from;      // from (inclusive)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   465
  int              _to;        // to (exclusive)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   466
  Range*           _next;      // linear list of Ranges
489c9b5090e2 Initial load
duke
parents:
diff changeset
   467
489c9b5090e2 Initial load
duke
parents:
diff changeset
   468
  // used only by class Interval, so hide them
489c9b5090e2 Initial load
duke
parents:
diff changeset
   469
  bool             intersects(Range* r) const    { return intersects_at(r) != -1; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   470
  int              intersects_at(Range* r) const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   471
489c9b5090e2 Initial load
duke
parents:
diff changeset
   472
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   473
  Range(int from, int to, Range* next);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   474
5707
6c66849ed24e 6958292: C1: Enable parallel compilation
iveresov
parents: 5547
diff changeset
   475
  static void      initialize(Arena* arena);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   476
  static Range*    end()                         { return _end; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   477
489c9b5090e2 Initial load
duke
parents:
diff changeset
   478
  int              from() const                  { return _from; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   479
  int              to()   const                  { return _to; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   480
  Range*           next() const                  { return _next; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   481
  void             set_from(int from)            { _from = from; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   482
  void             set_to(int to)                { _to = to; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   483
  void             set_next(Range* next)         { _next = next; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   484
489c9b5090e2 Initial load
duke
parents:
diff changeset
   485
  // for testing
489c9b5090e2 Initial load
duke
parents:
diff changeset
   486
  void             print(outputStream* out = tty) const PRODUCT_RETURN;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   487
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   488
489c9b5090e2 Initial load
duke
parents:
diff changeset
   489
489c9b5090e2 Initial load
duke
parents:
diff changeset
   490
// Interval is an ordered list of disjoint ranges.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   491
489c9b5090e2 Initial load
duke
parents:
diff changeset
   492
// For pre-colored double word LIR_Oprs, one interval is created for
489c9b5090e2 Initial load
duke
parents:
diff changeset
   493
// the low word register and one is created for the hi word register.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   494
// On Intel for FPU double registers only one interval is created.  At
489c9b5090e2 Initial load
duke
parents:
diff changeset
   495
// all times assigned_reg contains the reg. number of the physical
489c9b5090e2 Initial load
duke
parents:
diff changeset
   496
// register.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   497
489c9b5090e2 Initial load
duke
parents:
diff changeset
   498
// For LIR_Opr in virtual registers a single interval can represent
489c9b5090e2 Initial load
duke
parents:
diff changeset
   499
// single and double word values.  When a physical register is
489c9b5090e2 Initial load
duke
parents:
diff changeset
   500
// assigned to the interval, assigned_reg contains the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   501
// phys. reg. number and for double word values assigned_regHi the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   502
// phys. reg. number of the hi word if there is any.  For spilled
489c9b5090e2 Initial load
duke
parents:
diff changeset
   503
// intervals assigned_reg contains the stack index.  assigned_regHi is
489c9b5090e2 Initial load
duke
parents:
diff changeset
   504
// always -1.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   505
489c9b5090e2 Initial load
duke
parents:
diff changeset
   506
class Interval : public CompilationResourceObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   507
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   508
  static Interval* _end;          // sentinel (interval with only range Range::end())
489c9b5090e2 Initial load
duke
parents:
diff changeset
   509
489c9b5090e2 Initial load
duke
parents:
diff changeset
   510
  int              _reg_num;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   511
  BasicType        _type;         // valid only for virtual registers
489c9b5090e2 Initial load
duke
parents:
diff changeset
   512
  Range*           _first;        // sorted list of Ranges
489c9b5090e2 Initial load
duke
parents:
diff changeset
   513
  intStack         _use_pos_and_kinds; // sorted list of use-positions and their according use-kinds
489c9b5090e2 Initial load
duke
parents:
diff changeset
   514
489c9b5090e2 Initial load
duke
parents:
diff changeset
   515
  Range*           _current;      // interval iteration: the current Range
489c9b5090e2 Initial load
duke
parents:
diff changeset
   516
  Interval*        _next;         // interval iteration: sorted list of Intervals (ends with sentinel)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   517
  IntervalState    _state;        // interval iteration: to which set belongs this interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
   518
489c9b5090e2 Initial load
duke
parents:
diff changeset
   519
489c9b5090e2 Initial load
duke
parents:
diff changeset
   520
  int              _assigned_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   521
  int              _assigned_regHi;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   522
489c9b5090e2 Initial load
duke
parents:
diff changeset
   523
  int              _cached_to;    // cached value: to of last range (-1: not cached)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   524
  LIR_Opr          _cached_opr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   525
  VMReg            _cached_vm_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   526
489c9b5090e2 Initial load
duke
parents:
diff changeset
   527
  Interval*        _split_parent;           // the original interval where this interval is derived from
489c9b5090e2 Initial load
duke
parents:
diff changeset
   528
  IntervalList     _split_children;         // list of all intervals that are split off from this interval (only available for split parents)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   529
  Interval*        _current_split_child;    // the current split child that has been active or inactive last (always stored in split parents)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   530
489c9b5090e2 Initial load
duke
parents:
diff changeset
   531
  int              _canonical_spill_slot;   // the stack slot where all split parts of this interval are spilled to (always stored in split parents)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   532
  bool             _insert_move_when_activated; // true if move is inserted between _current_split_child and this interval when interval gets active the first time
489c9b5090e2 Initial load
duke
parents:
diff changeset
   533
  IntervalSpillState _spill_state;          // for spill move optimization
489c9b5090e2 Initial load
duke
parents:
diff changeset
   534
  int              _spill_definition_pos;   // position where the interval is defined (if defined only once)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   535
  Interval*        _register_hint;          // this interval should be in the same register as the hint interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
   536
489c9b5090e2 Initial load
duke
parents:
diff changeset
   537
  int              calc_to();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   538
  Interval*        new_split_child();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   539
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   540
  Interval(int reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   541
5707
6c66849ed24e 6958292: C1: Enable parallel compilation
iveresov
parents: 5547
diff changeset
   542
  static void      initialize(Arena* arena);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   543
  static Interval* end()                         { return _end; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   544
489c9b5090e2 Initial load
duke
parents:
diff changeset
   545
  // accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
   546
  int              reg_num() const               { return _reg_num; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   547
  void             set_reg_num(int r)            { assert(_reg_num == -1, "cannot change reg_num"); _reg_num = r; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   548
  BasicType        type() const                  { assert(_reg_num == -1 || _reg_num >= LIR_OprDesc::vreg_base, "cannot access type for fixed interval"); return _type; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   549
  void             set_type(BasicType type)      { assert(_reg_num < LIR_OprDesc::vreg_base || _type == T_ILLEGAL || _type == type, "overwriting existing type"); _type = type; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   550
489c9b5090e2 Initial load
duke
parents:
diff changeset
   551
  Range*           first() const                 { return _first; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   552
  int              from() const                  { return _first->from(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   553
  int              to()                          { if (_cached_to == -1) _cached_to = calc_to(); assert(_cached_to == calc_to(), "invalid cached value"); return _cached_to; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   554
  int              num_use_positions() const     { return _use_pos_and_kinds.length() / 2; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   555
489c9b5090e2 Initial load
duke
parents:
diff changeset
   556
  Interval*        next() const                  { return _next; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   557
  Interval**       next_addr()                   { return &_next; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   558
  void             set_next(Interval* next)      { _next = next; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   559
489c9b5090e2 Initial load
duke
parents:
diff changeset
   560
  int              assigned_reg() const          { return _assigned_reg; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   561
  int              assigned_regHi() const        { return _assigned_regHi; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   562
  void             assign_reg(int reg)           { _assigned_reg = reg; _assigned_regHi = LinearScan::any_reg; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   563
  void             assign_reg(int reg,int regHi) { _assigned_reg = reg; _assigned_regHi = regHi; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   564
489c9b5090e2 Initial load
duke
parents:
diff changeset
   565
  Interval*        register_hint(bool search_split_child = true) const; // calculation needed
489c9b5090e2 Initial load
duke
parents:
diff changeset
   566
  void             set_register_hint(Interval* i) { _register_hint = i; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   567
489c9b5090e2 Initial load
duke
parents:
diff changeset
   568
  int              state() const                 { return _state; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   569
  void             set_state(IntervalState s)    { _state = s; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   570
489c9b5090e2 Initial load
duke
parents:
diff changeset
   571
  // access to split parent and split children
489c9b5090e2 Initial load
duke
parents:
diff changeset
   572
  bool             is_split_parent() const       { return _split_parent == this; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   573
  bool             is_split_child() const        { return _split_parent != this; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   574
  Interval*        split_parent() const          { assert(_split_parent->is_split_parent(), "must be"); return _split_parent; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   575
  Interval*        split_child_at_op_id(int op_id, LIR_OpVisitState::OprMode mode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   576
  Interval*        split_child_before_op_id(int op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   577
  bool             split_child_covers(int op_id, LIR_OpVisitState::OprMode mode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   578
  DEBUG_ONLY(void  check_split_children();)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   579
489c9b5090e2 Initial load
duke
parents:
diff changeset
   580
  // information stored in split parent, but available for all children
489c9b5090e2 Initial load
duke
parents:
diff changeset
   581
  int              canonical_spill_slot() const            { return split_parent()->_canonical_spill_slot; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   582
  void             set_canonical_spill_slot(int slot)      { assert(split_parent()->_canonical_spill_slot == -1, "overwriting existing value"); split_parent()->_canonical_spill_slot = slot; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   583
  Interval*        current_split_child() const             { return split_parent()->_current_split_child; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   584
  void             make_current_split_child()              { split_parent()->_current_split_child = this; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   585
489c9b5090e2 Initial load
duke
parents:
diff changeset
   586
  bool             insert_move_when_activated() const      { return _insert_move_when_activated; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   587
  void             set_insert_move_when_activated(bool b)  { _insert_move_when_activated = b; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   588
489c9b5090e2 Initial load
duke
parents:
diff changeset
   589
  // for spill optimization
489c9b5090e2 Initial load
duke
parents:
diff changeset
   590
  IntervalSpillState spill_state() const         { return split_parent()->_spill_state; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   591
  int              spill_definition_pos() const  { return split_parent()->_spill_definition_pos; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   592
  void             set_spill_state(IntervalSpillState state) {  assert(state >= spill_state(), "state cannot decrease"); split_parent()->_spill_state = state; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   593
  void             set_spill_definition_pos(int pos) { assert(spill_definition_pos() == -1, "cannot set the position twice"); split_parent()->_spill_definition_pos = pos; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   594
  // returns true if this interval has a shadow copy on the stack that is always correct
489c9b5090e2 Initial load
duke
parents:
diff changeset
   595
  bool             always_in_memory() const      { return split_parent()->_spill_state == storeAtDefinition || split_parent()->_spill_state == startInMemory; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   596
489c9b5090e2 Initial load
duke
parents:
diff changeset
   597
  // caching of values that take time to compute and are used multiple times
489c9b5090e2 Initial load
duke
parents:
diff changeset
   598
  LIR_Opr          cached_opr() const            { return _cached_opr; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   599
  VMReg            cached_vm_reg() const         { return _cached_vm_reg; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   600
  void             set_cached_opr(LIR_Opr opr)   { _cached_opr = opr; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   601
  void             set_cached_vm_reg(VMReg reg)  { _cached_vm_reg = reg; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   602
489c9b5090e2 Initial load
duke
parents:
diff changeset
   603
  // access to use positions
489c9b5090e2 Initial load
duke
parents:
diff changeset
   604
  int    first_usage(IntervalUseKind min_use_kind) const;           // id of the first operation requiring this interval in a register
489c9b5090e2 Initial load
duke
parents:
diff changeset
   605
  int    next_usage(IntervalUseKind min_use_kind, int from) const;  // id of next usage seen from the given position
489c9b5090e2 Initial load
duke
parents:
diff changeset
   606
  int    next_usage_exact(IntervalUseKind exact_use_kind, int from) const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   607
  int    previous_usage(IntervalUseKind min_use_kind, int from) const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   608
489c9b5090e2 Initial load
duke
parents:
diff changeset
   609
  // manipulating intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
   610
  void   add_use_pos(int pos, IntervalUseKind use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   611
  void   add_range(int from, int to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   612
  Interval* split(int split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   613
  Interval* split_from_start(int split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   614
  void remove_first_use_pos()                    { _use_pos_and_kinds.truncate(_use_pos_and_kinds.length() - 2); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   615
489c9b5090e2 Initial load
duke
parents:
diff changeset
   616
  // test intersection
489c9b5090e2 Initial load
duke
parents:
diff changeset
   617
  bool   covers(int op_id, LIR_OpVisitState::OprMode mode) const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   618
  bool   has_hole_between(int from, int to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   619
  bool   intersects(Interval* i) const           { return _first->intersects(i->_first); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   620
  int    intersects_at(Interval* i) const        { return _first->intersects_at(i->_first); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   621
489c9b5090e2 Initial load
duke
parents:
diff changeset
   622
  // range iteration
489c9b5090e2 Initial load
duke
parents:
diff changeset
   623
  void   rewind_range()                          { _current = _first; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   624
  void   next_range()                            { assert(this != _end, "not allowed on sentinel"); _current = _current->next(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   625
  int    current_from() const                    { return _current->from(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   626
  int    current_to() const                      { return _current->to(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   627
  bool   current_at_end() const                  { return _current == Range::end(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   628
  bool   current_intersects(Interval* it)        { return _current->intersects(it->_current); };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   629
  int    current_intersects_at(Interval* it)     { return _current->intersects_at(it->_current); };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   630
489c9b5090e2 Initial load
duke
parents:
diff changeset
   631
  // printing
489c9b5090e2 Initial load
duke
parents:
diff changeset
   632
  void print(outputStream* out = tty) const      PRODUCT_RETURN;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   633
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   634
489c9b5090e2 Initial load
duke
parents:
diff changeset
   635
489c9b5090e2 Initial load
duke
parents:
diff changeset
   636
class IntervalWalker : public CompilationResourceObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   637
 protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   638
  Compilation*     _compilation;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   639
  LinearScan*      _allocator;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   640
489c9b5090e2 Initial load
duke
parents:
diff changeset
   641
  Interval*        _unhandled_first[nofKinds];  // sorted list of intervals, not life before the current position
489c9b5090e2 Initial load
duke
parents:
diff changeset
   642
  Interval*        _active_first   [nofKinds];  // sorted list of intervals, life at the current position
489c9b5090e2 Initial load
duke
parents:
diff changeset
   643
  Interval*        _inactive_first [nofKinds];  // sorted list of intervals, intervals in a life time hole at the current position
489c9b5090e2 Initial load
duke
parents:
diff changeset
   644
489c9b5090e2 Initial load
duke
parents:
diff changeset
   645
  Interval*        _current;                     // the current interval coming from unhandled list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   646
  int              _current_position;            // the current position (intercept point through the intervals)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   647
  IntervalKind     _current_kind;                // and whether it is fixed_kind or any_kind.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   648
489c9b5090e2 Initial load
duke
parents:
diff changeset
   649
489c9b5090e2 Initial load
duke
parents:
diff changeset
   650
  Compilation*     compilation() const               { return _compilation; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   651
  LinearScan*      allocator() const                 { return _allocator; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   652
489c9b5090e2 Initial load
duke
parents:
diff changeset
   653
  // unified bailout support
489c9b5090e2 Initial load
duke
parents:
diff changeset
   654
  void             bailout(const char* msg) const    { compilation()->bailout(msg); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   655
  bool             bailed_out() const                { return compilation()->bailed_out(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   656
489c9b5090e2 Initial load
duke
parents:
diff changeset
   657
  void check_bounds(IntervalKind kind) { assert(kind >= fixedKind && kind <= anyKind, "invalid interval_kind"); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   658
489c9b5090e2 Initial load
duke
parents:
diff changeset
   659
  Interval** unhandled_first_addr(IntervalKind kind) { check_bounds(kind); return &_unhandled_first[kind]; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   660
  Interval** active_first_addr(IntervalKind kind)    { check_bounds(kind); return &_active_first[kind]; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   661
  Interval** inactive_first_addr(IntervalKind kind)  { check_bounds(kind); return &_inactive_first[kind]; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   662
489c9b5090e2 Initial load
duke
parents:
diff changeset
   663
  void append_unsorted(Interval** first, Interval* interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   664
  void append_sorted(Interval** first, Interval* interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   665
  void append_to_unhandled(Interval** list, Interval* interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   666
489c9b5090e2 Initial load
duke
parents:
diff changeset
   667
  bool remove_from_list(Interval** list, Interval* i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   668
  void remove_from_list(Interval* i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   669
489c9b5090e2 Initial load
duke
parents:
diff changeset
   670
  void next_interval();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   671
  Interval*        current() const               { return _current; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   672
  IntervalKind     current_kind() const          { return _current_kind; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   673
489c9b5090e2 Initial load
duke
parents:
diff changeset
   674
  void walk_to(IntervalState state, int from);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   675
489c9b5090e2 Initial load
duke
parents:
diff changeset
   676
  // activate_current() is called when an unhandled interval becomes active (in current(), current_kind()).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   677
  // Return false if current() should not be moved the the active interval list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   678
  // It is safe to append current to any interval list but the unhandled list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   679
  virtual bool activate_current() { return true; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   680
489c9b5090e2 Initial load
duke
parents:
diff changeset
   681
  // interval_moved() is called whenever an interval moves from one interval list to another.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   682
  // In the implementation of this method it is prohibited to move the interval to any list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   683
  virtual void interval_moved(Interval* interval, IntervalKind kind, IntervalState from, IntervalState to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   684
489c9b5090e2 Initial load
duke
parents:
diff changeset
   685
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   686
  IntervalWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   687
489c9b5090e2 Initial load
duke
parents:
diff changeset
   688
  Interval* unhandled_first(IntervalKind kind)   { check_bounds(kind); return _unhandled_first[kind]; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   689
  Interval* active_first(IntervalKind kind)      { check_bounds(kind); return _active_first[kind]; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   690
  Interval* inactive_first(IntervalKind kind)    { check_bounds(kind); return _inactive_first[kind]; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   691
489c9b5090e2 Initial load
duke
parents:
diff changeset
   692
  // active contains the intervals that are live after the lir_op
489c9b5090e2 Initial load
duke
parents:
diff changeset
   693
  void walk_to(int lir_op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   694
  // active contains the intervals that are live before the lir_op
489c9b5090e2 Initial load
duke
parents:
diff changeset
   695
  void walk_before(int lir_op_id)  { walk_to(lir_op_id-1); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   696
  // walk through all intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
   697
  void walk()                      { walk_to(max_jint); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   698
489c9b5090e2 Initial load
duke
parents:
diff changeset
   699
  int current_position()           { return _current_position; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   700
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   701
489c9b5090e2 Initial load
duke
parents:
diff changeset
   702
489c9b5090e2 Initial load
duke
parents:
diff changeset
   703
// The actual linear scan register allocator
489c9b5090e2 Initial load
duke
parents:
diff changeset
   704
class LinearScanWalker : public IntervalWalker {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   705
  enum {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   706
    any_reg = LinearScan::any_reg
489c9b5090e2 Initial load
duke
parents:
diff changeset
   707
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   708
489c9b5090e2 Initial load
duke
parents:
diff changeset
   709
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   710
  int              _first_reg;       // the reg. number of the first phys. register
489c9b5090e2 Initial load
duke
parents:
diff changeset
   711
  int              _last_reg;        // the reg. nmber of the last phys. register
489c9b5090e2 Initial load
duke
parents:
diff changeset
   712
  int              _num_phys_regs;   // required by current interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
   713
  bool             _adjacent_regs;   // have lo/hi words of phys. regs be adjacent
489c9b5090e2 Initial load
duke
parents:
diff changeset
   714
489c9b5090e2 Initial load
duke
parents:
diff changeset
   715
  int              _use_pos[LinearScan::nof_regs];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   716
  int              _block_pos[LinearScan::nof_regs];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   717
  IntervalList*    _spill_intervals[LinearScan::nof_regs];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   718
489c9b5090e2 Initial load
duke
parents:
diff changeset
   719
  MoveResolver     _move_resolver;   // for ordering spill moves
489c9b5090e2 Initial load
duke
parents:
diff changeset
   720
489c9b5090e2 Initial load
duke
parents:
diff changeset
   721
  // accessors mapped to same functions in class LinearScan
489c9b5090e2 Initial load
duke
parents:
diff changeset
   722
  int         block_count() const      { return allocator()->block_count(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   723
  BlockBegin* block_at(int idx) const  { return allocator()->block_at(idx); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   724
  BlockBegin* block_of_op_with_id(int op_id) const { return allocator()->block_of_op_with_id(op_id); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   725
489c9b5090e2 Initial load
duke
parents:
diff changeset
   726
  void init_use_lists(bool only_process_use_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   727
  void exclude_from_use(int reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   728
  void exclude_from_use(Interval* i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   729
  void set_use_pos(int reg, Interval* i, int use_pos, bool only_process_use_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   730
  void set_use_pos(Interval* i, int use_pos, bool only_process_use_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   731
  void set_block_pos(int reg, Interval* i, int block_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   732
  void set_block_pos(Interval* i, int block_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   733
489c9b5090e2 Initial load
duke
parents:
diff changeset
   734
  void free_exclude_active_fixed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   735
  void free_exclude_active_any();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   736
  void free_collect_inactive_fixed(Interval* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   737
  void free_collect_inactive_any(Interval* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   738
  void free_collect_unhandled(IntervalKind kind, Interval* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   739
  void spill_exclude_active_fixed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   740
  void spill_block_unhandled_fixed(Interval* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   741
  void spill_block_inactive_fixed(Interval* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   742
  void spill_collect_active_any();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   743
  void spill_collect_inactive_any(Interval* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   744
489c9b5090e2 Initial load
duke
parents:
diff changeset
   745
  void insert_move(int op_id, Interval* src_it, Interval* dst_it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   746
  int  find_optimal_split_pos(BlockBegin* min_block, BlockBegin* max_block, int max_split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   747
  int  find_optimal_split_pos(Interval* it, int min_split_pos, int max_split_pos, bool do_loop_optimization);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   748
  void split_before_usage(Interval* it, int min_split_pos, int max_split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   749
  void split_for_spilling(Interval* it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   750
  void split_stack_interval(Interval* it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   751
  void split_when_partial_register_available(Interval* it, int register_available_until);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   752
  void split_and_spill_interval(Interval* it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   753
489c9b5090e2 Initial load
duke
parents:
diff changeset
   754
  int  find_free_reg(int reg_needed_until, int interval_to, int hint_reg, int ignore_reg, bool* need_split);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   755
  int  find_free_double_reg(int reg_needed_until, int interval_to, int hint_reg, bool* need_split);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   756
  bool alloc_free_reg(Interval* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   757
489c9b5090e2 Initial load
duke
parents:
diff changeset
   758
  int  find_locked_reg(int reg_needed_until, int interval_to, int hint_reg, int ignore_reg, bool* need_split);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   759
  int  find_locked_double_reg(int reg_needed_until, int interval_to, int hint_reg, bool* need_split);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   760
  void split_and_spill_intersecting_intervals(int reg, int regHi);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   761
  void alloc_locked_reg(Interval* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   762
489c9b5090e2 Initial load
duke
parents:
diff changeset
   763
  bool no_allocation_possible(Interval* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   764
  void update_phys_reg_range(bool requires_cpu_register);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   765
  void init_vars_for_alloc(Interval* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   766
  bool pd_init_regs_for_alloc(Interval* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   767
489c9b5090e2 Initial load
duke
parents:
diff changeset
   768
  void combine_spilled_intervals(Interval* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   769
  bool is_move(LIR_Op* op, Interval* from, Interval* to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   770
489c9b5090e2 Initial load
duke
parents:
diff changeset
   771
  bool activate_current();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   772
489c9b5090e2 Initial load
duke
parents:
diff changeset
   773
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   774
  LinearScanWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   775
489c9b5090e2 Initial load
duke
parents:
diff changeset
   776
  // must be called when all intervals are allocated
489c9b5090e2 Initial load
duke
parents:
diff changeset
   777
  void             finish_allocation()           { _move_resolver.resolve_and_append_moves(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   778
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   779
489c9b5090e2 Initial load
duke
parents:
diff changeset
   780
489c9b5090e2 Initial load
duke
parents:
diff changeset
   781
489c9b5090e2 Initial load
duke
parents:
diff changeset
   782
/*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   783
When a block has more than one predecessor, and all predecessors end with
489c9b5090e2 Initial load
duke
parents:
diff changeset
   784
the same sequence of move-instructions, than this moves can be placed once
489c9b5090e2 Initial load
duke
parents:
diff changeset
   785
at the beginning of the block instead of multiple times in the predecessors.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   786
489c9b5090e2 Initial load
duke
parents:
diff changeset
   787
Similarly, when a block has more than one successor, then equal sequences of
489c9b5090e2 Initial load
duke
parents:
diff changeset
   788
moves at the beginning of the successors can be placed once at the end of
489c9b5090e2 Initial load
duke
parents:
diff changeset
   789
the block. But because the moves must be inserted before all branch
489c9b5090e2 Initial load
duke
parents:
diff changeset
   790
instructions, this works only when there is exactly one conditional branch
489c9b5090e2 Initial load
duke
parents:
diff changeset
   791
at the end of the block (because the moves must be inserted before all
489c9b5090e2 Initial load
duke
parents:
diff changeset
   792
branches, but after all compares).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   793
489c9b5090e2 Initial load
duke
parents:
diff changeset
   794
This optimization affects all kind of moves (reg->reg, reg->stack and
489c9b5090e2 Initial load
duke
parents:
diff changeset
   795
stack->reg). Because this optimization works best when a block contains only
489c9b5090e2 Initial load
duke
parents:
diff changeset
   796
few moves, it has a huge impact on the number of blocks that are totally
489c9b5090e2 Initial load
duke
parents:
diff changeset
   797
empty.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   798
*/
489c9b5090e2 Initial load
duke
parents:
diff changeset
   799
class EdgeMoveOptimizer : public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   800
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   801
  // the class maintains a list with all lir-instruction-list of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   802
  // successors (predecessors) and the current index into the lir-lists
489c9b5090e2 Initial load
duke
parents:
diff changeset
   803
  LIR_OpListStack _edge_instructions;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   804
  intStack        _edge_instructions_idx;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   805
489c9b5090e2 Initial load
duke
parents:
diff changeset
   806
  void init_instructions();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   807
  void append_instructions(LIR_OpList* instructions, int instructions_idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   808
  LIR_Op* instruction_at(int edge);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   809
  void remove_cur_instruction(int edge, bool decrement_index);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   810
489c9b5090e2 Initial load
duke
parents:
diff changeset
   811
  bool operations_different(LIR_Op* op1, LIR_Op* op2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   812
489c9b5090e2 Initial load
duke
parents:
diff changeset
   813
  void optimize_moves_at_block_end(BlockBegin* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   814
  void optimize_moves_at_block_begin(BlockBegin* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   815
489c9b5090e2 Initial load
duke
parents:
diff changeset
   816
  EdgeMoveOptimizer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   817
489c9b5090e2 Initial load
duke
parents:
diff changeset
   818
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   819
  static void optimize(BlockList* code);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   820
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   821
489c9b5090e2 Initial load
duke
parents:
diff changeset
   822
489c9b5090e2 Initial load
duke
parents:
diff changeset
   823
489c9b5090e2 Initial load
duke
parents:
diff changeset
   824
class ControlFlowOptimizer : public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   825
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   826
  BlockList _original_preds;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   827
489c9b5090e2 Initial load
duke
parents:
diff changeset
   828
  enum {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   829
    ShortLoopSize = 5
489c9b5090e2 Initial load
duke
parents:
diff changeset
   830
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   831
  void reorder_short_loop(BlockList* code, BlockBegin* header_block, int header_idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   832
  void reorder_short_loops(BlockList* code);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   833
489c9b5090e2 Initial load
duke
parents:
diff changeset
   834
  bool can_delete_block(BlockBegin* cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   835
  void substitute_branch_target(BlockBegin* cur, BlockBegin* target_from, BlockBegin* target_to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   836
  void delete_empty_blocks(BlockList* code);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   837
489c9b5090e2 Initial load
duke
parents:
diff changeset
   838
  void delete_unnecessary_jumps(BlockList* code);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   839
  void delete_jumps_to_return(BlockList* code);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   840
489c9b5090e2 Initial load
duke
parents:
diff changeset
   841
  DEBUG_ONLY(void verify(BlockList* code);)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   842
489c9b5090e2 Initial load
duke
parents:
diff changeset
   843
  ControlFlowOptimizer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   844
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   845
  static void optimize(BlockList* code);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   846
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   847
489c9b5090e2 Initial load
duke
parents:
diff changeset
   848
489c9b5090e2 Initial load
duke
parents:
diff changeset
   849
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   850
489c9b5090e2 Initial load
duke
parents:
diff changeset
   851
// Helper class for collecting statistics of LinearScan
489c9b5090e2 Initial load
duke
parents:
diff changeset
   852
class LinearScanStatistic : public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   853
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   854
  enum Counter {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   855
    // general counters
489c9b5090e2 Initial load
duke
parents:
diff changeset
   856
    counter_method,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   857
    counter_fpu_method,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   858
    counter_loop_method,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   859
    counter_exception_method,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   860
    counter_loop,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   861
    counter_block,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   862
    counter_loop_block,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   863
    counter_exception_block,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   864
    counter_interval,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   865
    counter_fixed_interval,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   866
    counter_range,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   867
    counter_fixed_range,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   868
    counter_use_pos,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   869
    counter_fixed_use_pos,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   870
    counter_spill_slots,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   871
    blank_line_1,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   872
489c9b5090e2 Initial load
duke
parents:
diff changeset
   873
    // counter for classes of lir instructions
489c9b5090e2 Initial load
duke
parents:
diff changeset
   874
    counter_instruction,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   875
    counter_label,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   876
    counter_entry,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   877
    counter_return,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   878
    counter_call,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   879
    counter_move,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   880
    counter_cmp,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   881
    counter_cond_branch,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   882
    counter_uncond_branch,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   883
    counter_stub_branch,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   884
    counter_alu,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   885
    counter_alloc,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   886
    counter_sync,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   887
    counter_throw,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   888
    counter_unwind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   889
    counter_typecheck,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   890
    counter_fpu_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   891
    counter_misc_inst,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   892
    counter_other_inst,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   893
    blank_line_2,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   894
489c9b5090e2 Initial load
duke
parents:
diff changeset
   895
    // counter for different types of moves
489c9b5090e2 Initial load
duke
parents:
diff changeset
   896
    counter_move_total,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   897
    counter_move_reg_reg,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   898
    counter_move_reg_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   899
    counter_move_stack_reg,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   900
    counter_move_stack_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   901
    counter_move_reg_mem,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   902
    counter_move_mem_reg,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   903
    counter_move_const_any,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   904
489c9b5090e2 Initial load
duke
parents:
diff changeset
   905
    number_of_counters,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   906
    invalid_counter = -1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   907
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   908
489c9b5090e2 Initial load
duke
parents:
diff changeset
   909
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   910
  int _counters_sum[number_of_counters];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   911
  int _counters_max[number_of_counters];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   912
489c9b5090e2 Initial load
duke
parents:
diff changeset
   913
  void inc_counter(Counter idx, int value = 1) { _counters_sum[idx] += value; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   914
489c9b5090e2 Initial load
duke
parents:
diff changeset
   915
  const char* counter_name(int counter_idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   916
  Counter base_counter(int counter_idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   917
489c9b5090e2 Initial load
duke
parents:
diff changeset
   918
  void sum_up(LinearScanStatistic &method_statistic);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   919
  void collect(LinearScan* allocator);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   920
489c9b5090e2 Initial load
duke
parents:
diff changeset
   921
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   922
  LinearScanStatistic();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   923
  void print(const char* title);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   924
  static void compute(LinearScan* allocator, LinearScanStatistic &global_statistic);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   925
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   926
489c9b5090e2 Initial load
duke
parents:
diff changeset
   927
489c9b5090e2 Initial load
duke
parents:
diff changeset
   928
// Helper class for collecting compilation time of LinearScan
489c9b5090e2 Initial load
duke
parents:
diff changeset
   929
class LinearScanTimers : public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   930
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   931
  enum Timer {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   932
    timer_do_nothing,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   933
    timer_number_instructions,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   934
    timer_compute_local_live_sets,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   935
    timer_compute_global_live_sets,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   936
    timer_build_intervals,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   937
    timer_sort_intervals_before,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   938
    timer_allocate_registers,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   939
    timer_resolve_data_flow,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   940
    timer_sort_intervals_after,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   941
    timer_eliminate_spill_moves,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   942
    timer_assign_reg_num,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   943
    timer_allocate_fpu_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   944
    timer_optimize_lir,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   945
489c9b5090e2 Initial load
duke
parents:
diff changeset
   946
    number_of_timers
489c9b5090e2 Initial load
duke
parents:
diff changeset
   947
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   948
489c9b5090e2 Initial load
duke
parents:
diff changeset
   949
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   950
  elapsedTimer _timers[number_of_timers];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   951
  const char*  timer_name(int idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   952
489c9b5090e2 Initial load
duke
parents:
diff changeset
   953
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   954
  LinearScanTimers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   955
489c9b5090e2 Initial load
duke
parents:
diff changeset
   956
  void begin_method();                     // called for each method when register allocation starts
489c9b5090e2 Initial load
duke
parents:
diff changeset
   957
  void end_method(LinearScan* allocator);  // called for each method when register allocation completed
489c9b5090e2 Initial load
duke
parents:
diff changeset
   958
  void print(double total_time);           // called before termination of VM to print global summary
489c9b5090e2 Initial load
duke
parents:
diff changeset
   959
489c9b5090e2 Initial load
duke
parents:
diff changeset
   960
  elapsedTimer* timer(int idx) { return &(_timers[idx]); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   961
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   962
489c9b5090e2 Initial load
duke
parents:
diff changeset
   963
489c9b5090e2 Initial load
duke
parents:
diff changeset
   964
#endif // ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   965
489c9b5090e2 Initial load
duke
parents:
diff changeset
   966
489c9b5090e2 Initial load
duke
parents:
diff changeset
   967
// Pick up platform-dependent implementation details
7397
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
   968
#ifdef TARGET_ARCH_x86
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
   969
# include "c1_LinearScan_x86.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
   970
#endif
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
   971
#ifdef TARGET_ARCH_sparc
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
   972
# include "c1_LinearScan_sparc.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
   973
#endif
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
   974
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
   975
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
   976
#endif // SHARE_VM_C1_C1_LINEARSCAN_HPP