hotspot/src/share/vm/c1/c1_LinearScan.cpp
author iveresov
Thu, 02 Dec 2010 17:21:12 -0800
changeset 7432 f06f1253c317
parent 7427 d7b79a367474
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
/*
5547
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 5353
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: 5353
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 5353
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: 5353
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
#include "precompiled.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    26
#include "c1/c1_CFGPrinter.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    27
#include "c1/c1_CodeStubs.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    28
#include "c1/c1_Compilation.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_LIRGenerator.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    32
#include "c1/c1_LinearScan.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    33
#include "c1/c1_ValueStack.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    34
#include "utilities/bitMap.inline.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    35
#ifdef TARGET_ARCH_x86
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    36
# include "vmreg_x86.inline.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    37
#endif
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    38
#ifdef TARGET_ARCH_sparc
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    39
# include "vmreg_sparc.inline.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    40
#endif
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    41
#ifdef TARGET_ARCH_zero
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    42
# include "vmreg_zero.inline.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6745
diff changeset
    43
#endif
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
  static LinearScanStatistic _stat_before_alloc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
  static LinearScanStatistic _stat_after_asign;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
  static LinearScanStatistic _stat_final;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
  static LinearScanTimers _total_timer;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
  // helper macro for short definition of timer
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
  #define TIME_LINEAR_SCAN(timer_name)  TraceTime _block_timer("", _total_timer.timer(LinearScanTimers::timer_name), TimeLinearScan || TimeEachLinearScan, Verbose);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
  // helper macro for short definition of trace-output inside code
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
  #define TRACE_LINEAR_SCAN(level, code)       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
    if (TraceLinearScanLevel >= level) {       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
      code;                                    \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
  #define TIME_LINEAR_SCAN(timer_name)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
  #define TRACE_LINEAR_SCAN(level, code)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
// Map BasicType to spill size in 32-bit words, matching VMReg's notion of words
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
#ifdef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 0, 1, -1};
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, -1};
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
// Implementation of LinearScan
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
LinearScan::LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
 : _compilation(ir->compilation())
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
 , _ir(ir)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
 , _gen(gen)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
 , _frame_map(frame_map)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
 , _num_virtual_regs(gen->max_virtual_register_number())
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
 , _has_fpu_registers(false)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
 , _num_calls(-1)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
 , _max_spills(0)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
 , _unused_spill_slot(-1)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
 , _intervals(0)   // initialized later with correct length
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
 , _new_intervals_from_allocation(new IntervalList())
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
 , _sorted_intervals(NULL)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
 , _lir_ops(0)     // initialized later with correct length
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
 , _block_of_op(0) // initialized later with correct length
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
 , _has_info(0)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
 , _has_call(0)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
 , _scope_value_cache(0) // initialized later with correct length
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
 , _interval_in_loop(0, 0) // initialized later with correct length
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
 , _cached_blocks(*ir->linear_scan_order())
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
   100
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
 , _fpu_stack_allocator(NULL)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
  assert(this->ir() != NULL,          "check if valid");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
  assert(this->compilation() != NULL, "check if valid");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
  assert(this->gen() != NULL,         "check if valid");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
  assert(this->frame_map() != NULL,   "check if valid");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
// ********** functions for converting LIR-Operands to register numbers
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
// Emulate a flat register file comprising physical integer registers,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
// physical floating-point registers and virtual registers, in that order.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
// Virtual registers already have appropriate numbers, since V0 is
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
// the number of physical registers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
// Returns -1 for hi word if opr is a single word operand.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
// Note: the inverse operation (calculating an operand for register numbers)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
//       is done in calc_operand_for_interval()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
int LinearScan::reg_num(LIR_Opr opr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
  assert(opr->is_register(), "should not call this otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
  if (opr->is_virtual_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
    assert(opr->vreg_number() >= nof_regs, "found a virtual register with a fixed-register number");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
    return opr->vreg_number();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
  } else if (opr->is_single_cpu()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
    return opr->cpu_regnr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
  } else if (opr->is_double_cpu()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
    return opr->cpu_regnrLo();
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
   132
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
  } else if (opr->is_single_xmm()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
    return opr->fpu_regnr() + pd_first_xmm_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
  } else if (opr->is_double_xmm()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
    return opr->fpu_regnrLo() + pd_first_xmm_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
  } else if (opr->is_single_fpu()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
    return opr->fpu_regnr() + pd_first_fpu_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
  } else if (opr->is_double_fpu()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
    return opr->fpu_regnrLo() + pd_first_fpu_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
    ShouldNotReachHere();
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
   144
    return -1;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
int LinearScan::reg_numHi(LIR_Opr opr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
  assert(opr->is_register(), "should not call this otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
  if (opr->is_virtual_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
    return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
  } else if (opr->is_single_cpu()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
    return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
  } else if (opr->is_double_cpu()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
    return opr->cpu_regnrHi();
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
   157
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
  } else if (opr->is_single_xmm()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
    return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
  } else if (opr->is_double_xmm()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
    return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
  } else if (opr->is_single_fpu()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
    return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
  } else if (opr->is_double_fpu()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
    return opr->fpu_regnrHi() + pd_first_fpu_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
    ShouldNotReachHere();
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
   169
    return -1;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
// ********** functions for classification of intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
bool LinearScan::is_precolored_interval(const Interval* i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
  return i->reg_num() < LinearScan::nof_regs;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
bool LinearScan::is_virtual_interval(const Interval* i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
  return i->reg_num() >= LIR_OprDesc::vreg_base;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
bool LinearScan::is_precolored_cpu_interval(const Interval* i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
  return i->reg_num() < LinearScan::nof_cpu_regs;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
bool LinearScan::is_virtual_cpu_interval(const Interval* i) {
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
   189
#if defined(__SOFTFP__) || defined(E500V2)
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
   190
  return i->reg_num() >= LIR_OprDesc::vreg_base;
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
   191
#else
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
  return i->reg_num() >= LIR_OprDesc::vreg_base && (i->type() != T_FLOAT && i->type() != T_DOUBLE);
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
   193
#endif // __SOFTFP__ or E500V2
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
bool LinearScan::is_precolored_fpu_interval(const Interval* i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
  return i->reg_num() >= LinearScan::nof_cpu_regs && i->reg_num() < LinearScan::nof_regs;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
bool LinearScan::is_virtual_fpu_interval(const Interval* i) {
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
   201
#if defined(__SOFTFP__) || defined(E500V2)
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
   202
  return false;
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
   203
#else
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
  return i->reg_num() >= LIR_OprDesc::vreg_base && (i->type() == T_FLOAT || i->type() == T_DOUBLE);
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
   205
#endif // __SOFTFP__ or E500V2
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
bool LinearScan::is_in_fpu_register(const Interval* i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
  // fixed intervals not needed for FPU stack allocation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
  return i->reg_num() >= nof_regs && pd_first_fpu_reg <= i->assigned_reg() && i->assigned_reg() <= pd_last_fpu_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
bool LinearScan::is_oop_interval(const Interval* i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
  // fixed intervals never contain oops
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
  return i->reg_num() >= nof_regs && i->type() == T_OBJECT;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
// ********** General helper functions
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
// compute next unused stack index that can be used for spilling
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
int LinearScan::allocate_spill_slot(bool double_word) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
  int spill_slot;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
  if (double_word) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
    if ((_max_spills & 1) == 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
      // alignment of double-word values
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
      // the hole because of the alignment is filled with the next single-word value
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
      assert(_unused_spill_slot == -1, "wasting a spill slot");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
      _unused_spill_slot = _max_spills;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
      _max_spills++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
    spill_slot = _max_spills;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
    _max_spills += 2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
  } else if (_unused_spill_slot != -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
    // re-use hole that was the result of a previous double-word alignment
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
    spill_slot = _unused_spill_slot;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
    _unused_spill_slot = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
    spill_slot = _max_spills;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
    _max_spills++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
  int result = spill_slot + LinearScan::nof_regs + frame_map()->argcount();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
  // the class OopMapValue uses only 11 bits for storing the name of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
  // oop location. So a stack slot bigger than 2^11 leads to an overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
  // that is not reported in product builds. Prevent this by checking the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
  // spill slot here (altough this value and the later used location name
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
  // are slightly different)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
  if (result > 2000) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
    bailout("too many stack slots used");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
void LinearScan::assign_spill_slot(Interval* it) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
  // assign the canonical spill slot of the parent (if a part of the interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
  // is already spilled) or allocate a new spill slot
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
  if (it->canonical_spill_slot() >= 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
    it->assign_reg(it->canonical_spill_slot());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
    int spill = allocate_spill_slot(type2spill_size[it->type()] == 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
    it->set_canonical_spill_slot(spill);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
    it->assign_reg(spill);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
void LinearScan::propagate_spill_slots() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
  if (!frame_map()->finalize_frame(max_spills())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
    bailout("frame too large");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
// create a new interval with a predefined reg_num
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
// (only used for parent intervals that are created during the building phase)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
Interval* LinearScan::create_interval(int reg_num) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
  assert(_intervals.at(reg_num) == NULL, "overwriting exisiting interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
  Interval* interval = new Interval(reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
  _intervals.at_put(reg_num, interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
  // assign register number for precolored intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
  if (reg_num < LIR_OprDesc::vreg_base) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
    interval->assign_reg(reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
  return interval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
// assign a new reg_num to the interval and append it to the list of intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
// (only used for child intervals that are created during register allocation)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
void LinearScan::append_interval(Interval* it) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
  it->set_reg_num(_intervals.length());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
  _intervals.append(it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
  _new_intervals_from_allocation->append(it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
// copy the vreg-flags if an interval is split
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
void LinearScan::copy_register_flags(Interval* from, Interval* to) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
  if (gen()->is_vreg_flag_set(from->reg_num(), LIRGenerator::byte_reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
    gen()->set_vreg_flag(to->reg_num(), LIRGenerator::byte_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
  if (gen()->is_vreg_flag_set(from->reg_num(), LIRGenerator::callee_saved)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
    gen()->set_vreg_flag(to->reg_num(), LIRGenerator::callee_saved);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
  // Note: do not copy the must_start_in_memory flag because it is not necessary for child
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
  //       intervals (only the very beginning of the interval must be in memory)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
// ********** spill move optimization
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
// eliminate moves from register to stack if stack slot is known to be correct
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
// called during building of intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
void LinearScan::change_spill_definition_pos(Interval* interval, int def_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
  assert(interval->is_split_parent(), "can only be called for split parents");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
  switch (interval->spill_state()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
    case noDefinitionFound:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
      assert(interval->spill_definition_pos() == -1, "must no be set before");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
      interval->set_spill_definition_pos(def_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
      interval->set_spill_state(oneDefinitionFound);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
    case oneDefinitionFound:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
      assert(def_pos <= interval->spill_definition_pos(), "positions are processed in reverse order when intervals are created");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
      if (def_pos < interval->spill_definition_pos() - 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
        // second definition found, so no spill optimization possible for this interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
        interval->set_spill_state(noOptimization);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
        // two consecutive definitions (because of two-operand LIR form)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
        assert(block_of_op_with_id(def_pos) == block_of_op_with_id(interval->spill_definition_pos()), "block must be equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
    case noOptimization:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
      // nothing to do
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
    default:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
      assert(false, "other states not allowed at this time");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
// called during register allocation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
void LinearScan::change_spill_state(Interval* interval, int spill_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
  switch (interval->spill_state()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
    case oneDefinitionFound: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
      int def_loop_depth = block_of_op_with_id(interval->spill_definition_pos())->loop_depth();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
      int spill_loop_depth = block_of_op_with_id(spill_pos)->loop_depth();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
      if (def_loop_depth < spill_loop_depth) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
        // the loop depth of the spilling position is higher then the loop depth
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
        // at the definition of the interval -> move write to memory out of loop
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
        // by storing at definitin of the interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
        interval->set_spill_state(storeAtDefinition);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
        // the interval is currently spilled only once, so for now there is no
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
        // reason to store the interval at the definition
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
        interval->set_spill_state(oneMoveInserted);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
    case oneMoveInserted: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
      // the interval is spilled more then once, so it is better to store it to
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
      // memory at the definition
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
      interval->set_spill_state(storeAtDefinition);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
    case storeAtDefinition:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
    case startInMemory:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
    case noOptimization:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
    case noDefinitionFound:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
      // nothing to do
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
    default:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
      assert(false, "other states not allowed at this time");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
489c9b5090e2 Initial load
duke
parents:
diff changeset
   388
bool LinearScan::must_store_at_definition(const Interval* i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   389
  return i->is_split_parent() && i->spill_state() == storeAtDefinition;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   390
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   391
489c9b5090e2 Initial load
duke
parents:
diff changeset
   392
// called once before asignment of register numbers
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
void LinearScan::eliminate_spill_moves() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
  TIME_LINEAR_SCAN(timer_eliminate_spill_moves);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
  TRACE_LINEAR_SCAN(3, tty->print_cr("***** Eliminating unnecessary spill moves"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
  // collect all intervals that must be stored after their definion.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
  // the list is sorted by Interval::spill_definition_pos
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
  Interval* interval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
  Interval* temp_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
  create_unhandled_lists(&interval, &temp_list, must_store_at_definition, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
489c9b5090e2 Initial load
duke
parents:
diff changeset
   403
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   404
  Interval* prev = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   405
  Interval* temp = interval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   406
  while (temp != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   407
    assert(temp->spill_definition_pos() > 0, "invalid spill definition pos");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   408
    if (prev != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
      assert(temp->from() >= prev->from(), "intervals not sorted");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   410
      assert(temp->spill_definition_pos() >= prev->spill_definition_pos(), "when intervals are sorted by from, then they must also be sorted by spill_definition_pos");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   411
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   412
489c9b5090e2 Initial load
duke
parents:
diff changeset
   413
    assert(temp->canonical_spill_slot() >= LinearScan::nof_regs, "interval has no spill slot assigned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   414
    assert(temp->spill_definition_pos() >= temp->from(), "invalid order");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   415
    assert(temp->spill_definition_pos() <= temp->from() + 2, "only intervals defined once at their start-pos can be optimized");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   416
489c9b5090e2 Initial load
duke
parents:
diff changeset
   417
    TRACE_LINEAR_SCAN(4, tty->print_cr("interval %d (from %d to %d) must be stored at %d", temp->reg_num(), temp->from(), temp->to(), temp->spill_definition_pos()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   418
489c9b5090e2 Initial load
duke
parents:
diff changeset
   419
    temp = temp->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   420
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   421
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   422
489c9b5090e2 Initial load
duke
parents:
diff changeset
   423
  LIR_InsertionBuffer insertion_buffer;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   424
  int num_blocks = block_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   425
  for (int i = 0; i < num_blocks; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   426
    BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   427
    LIR_OpList* instructions = block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   428
    int         num_inst = instructions->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   429
    bool        has_new = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   430
489c9b5090e2 Initial load
duke
parents:
diff changeset
   431
    // iterate all instructions of the block. skip the first because it is always a label
489c9b5090e2 Initial load
duke
parents:
diff changeset
   432
    for (int j = 1; j < num_inst; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   433
      LIR_Op* op = instructions->at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   434
      int op_id = op->id();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   435
489c9b5090e2 Initial load
duke
parents:
diff changeset
   436
      if (op_id == -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   437
        // remove move from register to stack if the stack slot is guaranteed to be correct.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   438
        // only moves that have been inserted by LinearScan can be removed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   439
        assert(op->code() == lir_move, "only moves can have a op_id of -1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   440
        assert(op->as_Op1() != NULL, "move must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   441
        assert(op->as_Op1()->result_opr()->is_virtual(), "LinearScan inserts only moves to virtual registers");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   442
489c9b5090e2 Initial load
duke
parents:
diff changeset
   443
        LIR_Op1* op1 = (LIR_Op1*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   444
        Interval* interval = interval_at(op1->result_opr()->vreg_number());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   445
489c9b5090e2 Initial load
duke
parents:
diff changeset
   446
        if (interval->assigned_reg() >= LinearScan::nof_regs && interval->always_in_memory()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   447
          // move target is a stack slot that is always correct, so eliminate instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   448
          TRACE_LINEAR_SCAN(4, tty->print_cr("eliminating move from interval %d to %d", op1->in_opr()->vreg_number(), op1->result_opr()->vreg_number()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   449
          instructions->at_put(j, NULL); // NULL-instructions are deleted by assign_reg_num
489c9b5090e2 Initial load
duke
parents:
diff changeset
   450
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   451
489c9b5090e2 Initial load
duke
parents:
diff changeset
   452
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   453
        // insert move from register to stack just after the beginning of the interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
   454
        assert(interval == Interval::end() || interval->spill_definition_pos() >= op_id, "invalid order");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   455
        assert(interval == Interval::end() || (interval->is_split_parent() && interval->spill_state() == storeAtDefinition), "invalid interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   456
489c9b5090e2 Initial load
duke
parents:
diff changeset
   457
        while (interval != Interval::end() && interval->spill_definition_pos() == op_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   458
          if (!has_new) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   459
            // prepare insertion buffer (appended when all instructions of the block are processed)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   460
            insertion_buffer.init(block->lir());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   461
            has_new = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   462
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   463
489c9b5090e2 Initial load
duke
parents:
diff changeset
   464
          LIR_Opr from_opr = operand_for_interval(interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   465
          LIR_Opr to_opr = canonical_spill_opr(interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   466
          assert(from_opr->is_fixed_cpu() || from_opr->is_fixed_fpu(), "from operand must be a register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   467
          assert(to_opr->is_stack(), "to operand must be a stack slot");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   468
489c9b5090e2 Initial load
duke
parents:
diff changeset
   469
          insertion_buffer.move(j, from_opr, to_opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   470
          TRACE_LINEAR_SCAN(4, tty->print_cr("inserting move after definition of interval %d to stack slot %d at op_id %d", interval->reg_num(), interval->canonical_spill_slot() - LinearScan::nof_regs, op_id));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   471
489c9b5090e2 Initial load
duke
parents:
diff changeset
   472
          interval = interval->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   473
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   474
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   475
    } // end of instruction iteration
489c9b5090e2 Initial load
duke
parents:
diff changeset
   476
489c9b5090e2 Initial load
duke
parents:
diff changeset
   477
    if (has_new) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   478
      block->lir()->append(&insertion_buffer);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   479
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   480
  } // end of block iteration
489c9b5090e2 Initial load
duke
parents:
diff changeset
   481
489c9b5090e2 Initial load
duke
parents:
diff changeset
   482
  assert(interval == Interval::end(), "missed an interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   483
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   484
489c9b5090e2 Initial load
duke
parents:
diff changeset
   485
489c9b5090e2 Initial load
duke
parents:
diff changeset
   486
// ********** Phase 1: number all instructions in all blocks
489c9b5090e2 Initial load
duke
parents:
diff changeset
   487
// Compute depth-first and linear scan block orders, and number LIR_Op nodes for linear scan.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   488
489c9b5090e2 Initial load
duke
parents:
diff changeset
   489
void LinearScan::number_instructions() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   490
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   491
    // dummy-timer to measure the cost of the timer itself
489c9b5090e2 Initial load
duke
parents:
diff changeset
   492
    // (this time is then subtracted from all other timers to get the real value)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   493
    TIME_LINEAR_SCAN(timer_do_nothing);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   494
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   495
  TIME_LINEAR_SCAN(timer_number_instructions);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   496
489c9b5090e2 Initial load
duke
parents:
diff changeset
   497
  // Assign IDs to LIR nodes and build a mapping, lir_ops, from ID to LIR_Op node.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   498
  int num_blocks = block_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   499
  int num_instructions = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   500
  int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   501
  for (i = 0; i < num_blocks; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   502
    num_instructions += block_at(i)->lir()->instructions_list()->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   503
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   504
489c9b5090e2 Initial load
duke
parents:
diff changeset
   505
  // initialize with correct length
489c9b5090e2 Initial load
duke
parents:
diff changeset
   506
  _lir_ops = LIR_OpArray(num_instructions);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   507
  _block_of_op = BlockBeginArray(num_instructions);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   508
489c9b5090e2 Initial load
duke
parents:
diff changeset
   509
  int op_id = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   510
  int idx = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   511
489c9b5090e2 Initial load
duke
parents:
diff changeset
   512
  for (i = 0; i < num_blocks; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   513
    BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   514
    block->set_first_lir_instruction_id(op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   515
    LIR_OpList* instructions = block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   516
489c9b5090e2 Initial load
duke
parents:
diff changeset
   517
    int num_inst = instructions->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   518
    for (int j = 0; j < num_inst; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   519
      LIR_Op* op = instructions->at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   520
      op->set_id(op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   521
489c9b5090e2 Initial load
duke
parents:
diff changeset
   522
      _lir_ops.at_put(idx, op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   523
      _block_of_op.at_put(idx, block);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   524
      assert(lir_op_with_id(op_id) == op, "must match");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   525
489c9b5090e2 Initial load
duke
parents:
diff changeset
   526
      idx++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   527
      op_id += 2; // numbering of lir_ops by two
489c9b5090e2 Initial load
duke
parents:
diff changeset
   528
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   529
    block->set_last_lir_instruction_id(op_id - 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   530
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   531
  assert(idx == num_instructions, "must match");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   532
  assert(idx * 2 == op_id, "must match");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   533
489c9b5090e2 Initial load
duke
parents:
diff changeset
   534
  _has_call = BitMap(num_instructions); _has_call.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   535
  _has_info = BitMap(num_instructions); _has_info.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   536
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   537
489c9b5090e2 Initial load
duke
parents:
diff changeset
   538
489c9b5090e2 Initial load
duke
parents:
diff changeset
   539
// ********** Phase 2: compute local live sets separately for each block
489c9b5090e2 Initial load
duke
parents:
diff changeset
   540
// (sets live_gen and live_kill for each block)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   541
489c9b5090e2 Initial load
duke
parents:
diff changeset
   542
void LinearScan::set_live_gen_kill(Value value, LIR_Op* op, BitMap& live_gen, BitMap& live_kill) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   543
  LIR_Opr opr = value->operand();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   544
  Constant* con = value->as_Constant();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   545
489c9b5090e2 Initial load
duke
parents:
diff changeset
   546
  // check some asumptions about debug information
489c9b5090e2 Initial load
duke
parents:
diff changeset
   547
  assert(!value->type()->is_illegal(), "if this local is used by the interpreter it shouldn't be of indeterminate type");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   548
  assert(con == NULL || opr->is_virtual() || opr->is_constant() || opr->is_illegal(), "asumption: Constant instructions have only constant operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   549
  assert(con != NULL || opr->is_virtual(), "asumption: non-Constant instructions have only virtual operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   550
489c9b5090e2 Initial load
duke
parents:
diff changeset
   551
  if ((con == NULL || con->is_pinned()) && opr->is_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   552
    assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   553
    int reg = opr->vreg_number();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   554
    if (!live_kill.at(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   555
      live_gen.set_bit(reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   556
      TRACE_LINEAR_SCAN(4, tty->print_cr("  Setting live_gen for value %c%d, LIR op_id %d, register number %d", value->type()->tchar(), value->id(), op->id(), reg));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   557
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   558
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   559
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   560
489c9b5090e2 Initial load
duke
parents:
diff changeset
   561
489c9b5090e2 Initial load
duke
parents:
diff changeset
   562
void LinearScan::compute_local_live_sets() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   563
  TIME_LINEAR_SCAN(timer_compute_local_live_sets);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   564
489c9b5090e2 Initial load
duke
parents:
diff changeset
   565
  int  num_blocks = block_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   566
  int  live_size = live_set_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   567
  bool local_has_fpu_registers = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   568
  int  local_num_calls = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   569
  LIR_OpVisitState visitor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   570
489c9b5090e2 Initial load
duke
parents:
diff changeset
   571
  BitMap2D local_interval_in_loop = BitMap2D(_num_virtual_regs, num_loops());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   572
  local_interval_in_loop.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   573
489c9b5090e2 Initial load
duke
parents:
diff changeset
   574
  // iterate all blocks
489c9b5090e2 Initial load
duke
parents:
diff changeset
   575
  for (int i = 0; i < num_blocks; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   576
    BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   577
489c9b5090e2 Initial load
duke
parents:
diff changeset
   578
    BitMap live_gen(live_size);  live_gen.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   579
    BitMap live_kill(live_size); live_kill.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   580
489c9b5090e2 Initial load
duke
parents:
diff changeset
   581
    if (block->is_set(BlockBegin::exception_entry_flag)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   582
      // Phi functions at the begin of an exception handler are
489c9b5090e2 Initial load
duke
parents:
diff changeset
   583
      // implicitly defined (= killed) at the beginning of the block.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   584
      for_each_phi_fun(block, phi,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   585
        live_kill.set_bit(phi->operand()->vreg_number())
489c9b5090e2 Initial load
duke
parents:
diff changeset
   586
      );
489c9b5090e2 Initial load
duke
parents:
diff changeset
   587
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   588
489c9b5090e2 Initial load
duke
parents:
diff changeset
   589
    LIR_OpList* instructions = block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   590
    int num_inst = instructions->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   591
489c9b5090e2 Initial load
duke
parents:
diff changeset
   592
    // iterate all instructions of the block. skip the first because it is always a label
489c9b5090e2 Initial load
duke
parents:
diff changeset
   593
    assert(visitor.no_operands(instructions->at(0)), "first operation must always be a label");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   594
    for (int j = 1; j < num_inst; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   595
      LIR_Op* op = instructions->at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   596
489c9b5090e2 Initial load
duke
parents:
diff changeset
   597
      // visit operation to collect all operands
489c9b5090e2 Initial load
duke
parents:
diff changeset
   598
      visitor.visit(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   599
489c9b5090e2 Initial load
duke
parents:
diff changeset
   600
      if (visitor.has_call()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   601
        _has_call.set_bit(op->id() >> 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   602
        local_num_calls++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   603
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   604
      if (visitor.info_count() > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   605
        _has_info.set_bit(op->id() >> 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   606
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   607
489c9b5090e2 Initial load
duke
parents:
diff changeset
   608
      // iterate input operands of instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   609
      int k, n, reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   610
      n = visitor.opr_count(LIR_OpVisitState::inputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   611
      for (k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   612
        LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   613
        assert(opr->is_register(), "visitor should only return register operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   614
489c9b5090e2 Initial load
duke
parents:
diff changeset
   615
        if (opr->is_virtual_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   616
          assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   617
          reg = opr->vreg_number();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   618
          if (!live_kill.at(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   619
            live_gen.set_bit(reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   620
            TRACE_LINEAR_SCAN(4, tty->print_cr("  Setting live_gen for register %d at instruction %d", reg, op->id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   621
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   622
          if (block->loop_index() >= 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   623
            local_interval_in_loop.set_bit(reg, block->loop_index());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   624
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   625
          local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   626
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   627
489c9b5090e2 Initial load
duke
parents:
diff changeset
   628
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   629
        // fixed intervals are never live at block boundaries, so
489c9b5090e2 Initial load
duke
parents:
diff changeset
   630
        // they need not be processed in live sets.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   631
        // this is checked by these assertions to be sure about it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   632
        // the entry block may have incoming values in registers, which is ok.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   633
        if (!opr->is_virtual_register() && block != ir()->start()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   634
          reg = reg_num(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   635
          if (is_processed_reg_num(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   636
            assert(live_kill.at(reg), "using fixed register that is not defined in this block");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   637
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   638
          reg = reg_numHi(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   639
          if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   640
            assert(live_kill.at(reg), "using fixed register that is not defined in this block");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   641
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   642
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   643
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   644
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   645
489c9b5090e2 Initial load
duke
parents:
diff changeset
   646
      // Add uses of live locals from interpreter's point of view for proper debug information generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   647
      n = visitor.info_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   648
      for (k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   649
        CodeEmitInfo* info = visitor.info_at(k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   650
        ValueStack* stack = info->stack();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   651
        for_each_state_value(stack, value,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   652
          set_live_gen_kill(value, op, live_gen, live_kill)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   653
        );
489c9b5090e2 Initial load
duke
parents:
diff changeset
   654
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   655
489c9b5090e2 Initial load
duke
parents:
diff changeset
   656
      // iterate temp operands of instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   657
      n = visitor.opr_count(LIR_OpVisitState::tempMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   658
      for (k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   659
        LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   660
        assert(opr->is_register(), "visitor should only return register operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   661
489c9b5090e2 Initial load
duke
parents:
diff changeset
   662
        if (opr->is_virtual_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   663
          assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   664
          reg = opr->vreg_number();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   665
          live_kill.set_bit(reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   666
          if (block->loop_index() >= 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   667
            local_interval_in_loop.set_bit(reg, block->loop_index());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   668
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   669
          local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   670
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   671
489c9b5090e2 Initial load
duke
parents:
diff changeset
   672
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   673
        // fixed intervals are never live at block boundaries, so
489c9b5090e2 Initial load
duke
parents:
diff changeset
   674
        // they need not be processed in live sets
489c9b5090e2 Initial load
duke
parents:
diff changeset
   675
        // process them only in debug mode so that this can be checked
489c9b5090e2 Initial load
duke
parents:
diff changeset
   676
        if (!opr->is_virtual_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   677
          reg = reg_num(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   678
          if (is_processed_reg_num(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   679
            live_kill.set_bit(reg_num(opr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   680
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   681
          reg = reg_numHi(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   682
          if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   683
            live_kill.set_bit(reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   684
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   685
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   686
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   687
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   688
489c9b5090e2 Initial load
duke
parents:
diff changeset
   689
      // iterate output operands of instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   690
      n = visitor.opr_count(LIR_OpVisitState::outputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   691
      for (k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   692
        LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   693
        assert(opr->is_register(), "visitor should only return register operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   694
489c9b5090e2 Initial load
duke
parents:
diff changeset
   695
        if (opr->is_virtual_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   696
          assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   697
          reg = opr->vreg_number();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   698
          live_kill.set_bit(reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   699
          if (block->loop_index() >= 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   700
            local_interval_in_loop.set_bit(reg, block->loop_index());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   701
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   702
          local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   703
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   704
489c9b5090e2 Initial load
duke
parents:
diff changeset
   705
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   706
        // fixed intervals are never live at block boundaries, so
489c9b5090e2 Initial load
duke
parents:
diff changeset
   707
        // they need not be processed in live sets
489c9b5090e2 Initial load
duke
parents:
diff changeset
   708
        // process them only in debug mode so that this can be checked
489c9b5090e2 Initial load
duke
parents:
diff changeset
   709
        if (!opr->is_virtual_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   710
          reg = reg_num(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   711
          if (is_processed_reg_num(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   712
            live_kill.set_bit(reg_num(opr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   713
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   714
          reg = reg_numHi(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   715
          if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   716
            live_kill.set_bit(reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   717
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   718
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   719
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   720
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   721
    } // end of instruction iteration
489c9b5090e2 Initial load
duke
parents:
diff changeset
   722
489c9b5090e2 Initial load
duke
parents:
diff changeset
   723
    block->set_live_gen (live_gen);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   724
    block->set_live_kill(live_kill);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   725
    block->set_live_in  (BitMap(live_size)); block->live_in().clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   726
    block->set_live_out (BitMap(live_size)); block->live_out().clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   727
489c9b5090e2 Initial load
duke
parents:
diff changeset
   728
    TRACE_LINEAR_SCAN(4, tty->print("live_gen  B%d ", block->block_id()); print_bitmap(block->live_gen()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   729
    TRACE_LINEAR_SCAN(4, tty->print("live_kill B%d ", block->block_id()); print_bitmap(block->live_kill()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   730
  } // end of block iteration
489c9b5090e2 Initial load
duke
parents:
diff changeset
   731
489c9b5090e2 Initial load
duke
parents:
diff changeset
   732
  // propagate local calculated information into LinearScan object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   733
  _has_fpu_registers = local_has_fpu_registers;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   734
  compilation()->set_has_fpu_code(local_has_fpu_registers);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   735
489c9b5090e2 Initial load
duke
parents:
diff changeset
   736
  _num_calls = local_num_calls;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   737
  _interval_in_loop = local_interval_in_loop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   738
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   739
489c9b5090e2 Initial load
duke
parents:
diff changeset
   740
489c9b5090e2 Initial load
duke
parents:
diff changeset
   741
// ********** Phase 3: perform a backward dataflow analysis to compute global live sets
489c9b5090e2 Initial load
duke
parents:
diff changeset
   742
// (sets live_in and live_out for each block)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   743
489c9b5090e2 Initial load
duke
parents:
diff changeset
   744
void LinearScan::compute_global_live_sets() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   745
  TIME_LINEAR_SCAN(timer_compute_global_live_sets);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   746
489c9b5090e2 Initial load
duke
parents:
diff changeset
   747
  int  num_blocks = block_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   748
  bool change_occurred;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   749
  bool change_occurred_in_block;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   750
  int  iteration_count = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   751
  BitMap live_out(live_set_size()); live_out.clear(); // scratch set for calculations
489c9b5090e2 Initial load
duke
parents:
diff changeset
   752
489c9b5090e2 Initial load
duke
parents:
diff changeset
   753
  // Perform a backward dataflow analysis to compute live_out and live_in for each block.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   754
  // The loop is executed until a fixpoint is reached (no changes in an iteration)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   755
  // Exception handlers must be processed because not all live values are
489c9b5090e2 Initial load
duke
parents:
diff changeset
   756
  // present in the state array, e.g. because of global value numbering
489c9b5090e2 Initial load
duke
parents:
diff changeset
   757
  do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   758
    change_occurred = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   759
489c9b5090e2 Initial load
duke
parents:
diff changeset
   760
    // iterate all blocks in reverse order
489c9b5090e2 Initial load
duke
parents:
diff changeset
   761
    for (int i = num_blocks - 1; i >= 0; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   762
      BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   763
489c9b5090e2 Initial load
duke
parents:
diff changeset
   764
      change_occurred_in_block = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   765
489c9b5090e2 Initial load
duke
parents:
diff changeset
   766
      // live_out(block) is the union of live_in(sux), for successors sux of block
489c9b5090e2 Initial load
duke
parents:
diff changeset
   767
      int n = block->number_of_sux();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   768
      int e = block->number_of_exception_handlers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   769
      if (n + e > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   770
        // block has successors
489c9b5090e2 Initial load
duke
parents:
diff changeset
   771
        if (n > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   772
          live_out.set_from(block->sux_at(0)->live_in());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   773
          for (int j = 1; j < n; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   774
            live_out.set_union(block->sux_at(j)->live_in());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   775
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   776
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   777
          live_out.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   778
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   779
        for (int j = 0; j < e; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   780
          live_out.set_union(block->exception_handler_at(j)->live_in());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   781
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   782
489c9b5090e2 Initial load
duke
parents:
diff changeset
   783
        if (!block->live_out().is_same(live_out)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   784
          // A change occurred.  Swap the old and new live out sets to avoid copying.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   785
          BitMap temp = block->live_out();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   786
          block->set_live_out(live_out);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   787
          live_out = temp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   788
489c9b5090e2 Initial load
duke
parents:
diff changeset
   789
          change_occurred = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   790
          change_occurred_in_block = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   791
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   792
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   793
489c9b5090e2 Initial load
duke
parents:
diff changeset
   794
      if (iteration_count == 0 || change_occurred_in_block) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   795
        // live_in(block) is the union of live_gen(block) with (live_out(block) & !live_kill(block))
489c9b5090e2 Initial load
duke
parents:
diff changeset
   796
        // note: live_in has to be computed only in first iteration or if live_out has changed!
489c9b5090e2 Initial load
duke
parents:
diff changeset
   797
        BitMap live_in = block->live_in();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   798
        live_in.set_from(block->live_out());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   799
        live_in.set_difference(block->live_kill());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   800
        live_in.set_union(block->live_gen());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   801
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   802
489c9b5090e2 Initial load
duke
parents:
diff changeset
   803
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   804
      if (TraceLinearScanLevel >= 4) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   805
        char c = ' ';
489c9b5090e2 Initial load
duke
parents:
diff changeset
   806
        if (iteration_count == 0 || change_occurred_in_block) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   807
          c = '*';
489c9b5090e2 Initial load
duke
parents:
diff changeset
   808
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   809
        tty->print("(%d) live_in%c  B%d ", iteration_count, c, block->block_id()); print_bitmap(block->live_in());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   810
        tty->print("(%d) live_out%c B%d ", iteration_count, c, block->block_id()); print_bitmap(block->live_out());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   811
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   812
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   813
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   814
    iteration_count++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   815
489c9b5090e2 Initial load
duke
parents:
diff changeset
   816
    if (change_occurred && iteration_count > 50) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   817
      BAILOUT("too many iterations in compute_global_live_sets");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   818
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   819
  } while (change_occurred);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   820
489c9b5090e2 Initial load
duke
parents:
diff changeset
   821
489c9b5090e2 Initial load
duke
parents:
diff changeset
   822
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   823
  // check that fixed intervals are not live at block boundaries
489c9b5090e2 Initial load
duke
parents:
diff changeset
   824
  // (live set must be empty at fixed intervals)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   825
  for (int i = 0; i < num_blocks; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   826
    BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   827
    for (int j = 0; j < LIR_OprDesc::vreg_base; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   828
      assert(block->live_in().at(j)  == false, "live_in  set of fixed register must be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   829
      assert(block->live_out().at(j) == false, "live_out set of fixed register must be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   830
      assert(block->live_gen().at(j) == false, "live_gen set of fixed register must be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   831
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   832
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   833
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   834
489c9b5090e2 Initial load
duke
parents:
diff changeset
   835
  // check that the live_in set of the first block is empty
489c9b5090e2 Initial load
duke
parents:
diff changeset
   836
  BitMap live_in_args(ir()->start()->live_in().size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   837
  live_in_args.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   838
  if (!ir()->start()->live_in().is_same(live_in_args)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   839
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   840
    tty->print_cr("Error: live_in set of first block must be empty (when this fails, virtual registers are used before they are defined)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   841
    tty->print_cr("affected registers:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   842
    print_bitmap(ir()->start()->live_in());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   843
489c9b5090e2 Initial load
duke
parents:
diff changeset
   844
    // print some additional information to simplify debugging
489c9b5090e2 Initial load
duke
parents:
diff changeset
   845
    for (unsigned int i = 0; i < ir()->start()->live_in().size(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   846
      if (ir()->start()->live_in().at(i)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   847
        Instruction* instr = gen()->instruction_for_vreg(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   848
        tty->print_cr("* vreg %d (HIR instruction %c%d)", i, instr == NULL ? ' ' : instr->type()->tchar(), instr == NULL ? 0 : instr->id());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   849
489c9b5090e2 Initial load
duke
parents:
diff changeset
   850
        for (int j = 0; j < num_blocks; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   851
          BlockBegin* block = block_at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   852
          if (block->live_gen().at(i)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   853
            tty->print_cr("  used in block B%d", block->block_id());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   854
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   855
          if (block->live_kill().at(i)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   856
            tty->print_cr("  defined in block B%d", block->block_id());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   857
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   858
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   859
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   860
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   861
489c9b5090e2 Initial load
duke
parents:
diff changeset
   862
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   863
    // when this fails, virtual registers are used before they are defined.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   864
    assert(false, "live_in set of first block must be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   865
    // bailout of if this occurs in product mode.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   866
    bailout("live_in set of first block not empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   867
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   868
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   869
489c9b5090e2 Initial load
duke
parents:
diff changeset
   870
489c9b5090e2 Initial load
duke
parents:
diff changeset
   871
// ********** Phase 4: build intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
   872
// (fills the list _intervals)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   873
489c9b5090e2 Initial load
duke
parents:
diff changeset
   874
void LinearScan::add_use(Value value, int from, int to, IntervalUseKind use_kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   875
  assert(!value->type()->is_illegal(), "if this value is used by the interpreter it shouldn't be of indeterminate type");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   876
  LIR_Opr opr = value->operand();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   877
  Constant* con = value->as_Constant();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   878
489c9b5090e2 Initial load
duke
parents:
diff changeset
   879
  if ((con == NULL || con->is_pinned()) && opr->is_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   880
    assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   881
    add_use(opr, from, to, use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   882
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   883
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   884
489c9b5090e2 Initial load
duke
parents:
diff changeset
   885
489c9b5090e2 Initial load
duke
parents:
diff changeset
   886
void LinearScan::add_def(LIR_Opr opr, int def_pos, IntervalUseKind use_kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   887
  TRACE_LINEAR_SCAN(2, tty->print(" def "); opr->print(tty); tty->print_cr(" def_pos %d (%d)", def_pos, use_kind));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   888
  assert(opr->is_register(), "should not be called otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   889
489c9b5090e2 Initial load
duke
parents:
diff changeset
   890
  if (opr->is_virtual_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   891
    assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   892
    add_def(opr->vreg_number(), def_pos, use_kind, opr->type_register());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   893
489c9b5090e2 Initial load
duke
parents:
diff changeset
   894
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   895
    int reg = reg_num(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   896
    if (is_processed_reg_num(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   897
      add_def(reg, def_pos, use_kind, opr->type_register());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   898
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   899
    reg = reg_numHi(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   900
    if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   901
      add_def(reg, def_pos, use_kind, opr->type_register());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   902
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   903
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   904
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   905
489c9b5090e2 Initial load
duke
parents:
diff changeset
   906
void LinearScan::add_use(LIR_Opr opr, int from, int to, IntervalUseKind use_kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   907
  TRACE_LINEAR_SCAN(2, tty->print(" use "); opr->print(tty); tty->print_cr(" from %d to %d (%d)", from, to, use_kind));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   908
  assert(opr->is_register(), "should not be called otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   909
489c9b5090e2 Initial load
duke
parents:
diff changeset
   910
  if (opr->is_virtual_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   911
    assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   912
    add_use(opr->vreg_number(), from, to, use_kind, opr->type_register());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   913
489c9b5090e2 Initial load
duke
parents:
diff changeset
   914
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   915
    int reg = reg_num(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   916
    if (is_processed_reg_num(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   917
      add_use(reg, from, to, use_kind, opr->type_register());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   918
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   919
    reg = reg_numHi(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   920
    if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   921
      add_use(reg, from, to, use_kind, opr->type_register());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   922
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   923
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   924
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   925
489c9b5090e2 Initial load
duke
parents:
diff changeset
   926
void LinearScan::add_temp(LIR_Opr opr, int temp_pos, IntervalUseKind use_kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   927
  TRACE_LINEAR_SCAN(2, tty->print(" temp "); opr->print(tty); tty->print_cr(" temp_pos %d (%d)", temp_pos, use_kind));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   928
  assert(opr->is_register(), "should not be called otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   929
489c9b5090e2 Initial load
duke
parents:
diff changeset
   930
  if (opr->is_virtual_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   931
    assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   932
    add_temp(opr->vreg_number(), temp_pos, use_kind, opr->type_register());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   933
489c9b5090e2 Initial load
duke
parents:
diff changeset
   934
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   935
    int reg = reg_num(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   936
    if (is_processed_reg_num(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   937
      add_temp(reg, temp_pos, use_kind, opr->type_register());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   938
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   939
    reg = reg_numHi(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   940
    if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   941
      add_temp(reg, temp_pos, use_kind, opr->type_register());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   942
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   943
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   944
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   945
489c9b5090e2 Initial load
duke
parents:
diff changeset
   946
489c9b5090e2 Initial load
duke
parents:
diff changeset
   947
void LinearScan::add_def(int reg_num, int def_pos, IntervalUseKind use_kind, BasicType type) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   948
  Interval* interval = interval_at(reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   949
  if (interval != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   950
    assert(interval->reg_num() == reg_num, "wrong interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   951
489c9b5090e2 Initial load
duke
parents:
diff changeset
   952
    if (type != T_ILLEGAL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   953
      interval->set_type(type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   954
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   955
489c9b5090e2 Initial load
duke
parents:
diff changeset
   956
    Range* r = interval->first();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   957
    if (r->from() <= def_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   958
      // Update the starting point (when a range is first created for a use, its
489c9b5090e2 Initial load
duke
parents:
diff changeset
   959
      // start is the beginning of the current block until a def is encountered.)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   960
      r->set_from(def_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   961
      interval->add_use_pos(def_pos, use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   962
489c9b5090e2 Initial load
duke
parents:
diff changeset
   963
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   964
      // Dead value - make vacuous interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
   965
      // also add use_kind for dead intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
   966
      interval->add_range(def_pos, def_pos + 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   967
      interval->add_use_pos(def_pos, use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   968
      TRACE_LINEAR_SCAN(2, tty->print_cr("Warning: def of reg %d at %d occurs without use", reg_num, def_pos));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   969
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   970
489c9b5090e2 Initial load
duke
parents:
diff changeset
   971
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   972
    // Dead value - make vacuous interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
   973
    // also add use_kind for dead intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
   974
    interval = create_interval(reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   975
    if (type != T_ILLEGAL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   976
      interval->set_type(type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   977
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   978
489c9b5090e2 Initial load
duke
parents:
diff changeset
   979
    interval->add_range(def_pos, def_pos + 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   980
    interval->add_use_pos(def_pos, use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   981
    TRACE_LINEAR_SCAN(2, tty->print_cr("Warning: dead value %d at %d in live intervals", reg_num, def_pos));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   982
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   983
489c9b5090e2 Initial load
duke
parents:
diff changeset
   984
  change_spill_definition_pos(interval, def_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   985
  if (use_kind == noUse && interval->spill_state() <= startInMemory) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   986
        // detection of method-parameters and roundfp-results
489c9b5090e2 Initial load
duke
parents:
diff changeset
   987
        // TODO: move this directly to position where use-kind is computed
489c9b5090e2 Initial load
duke
parents:
diff changeset
   988
    interval->set_spill_state(startInMemory);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   989
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   990
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   991
489c9b5090e2 Initial load
duke
parents:
diff changeset
   992
void LinearScan::add_use(int reg_num, int from, int to, IntervalUseKind use_kind, BasicType type) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   993
  Interval* interval = interval_at(reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   994
  if (interval == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   995
    interval = create_interval(reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   996
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   997
  assert(interval->reg_num() == reg_num, "wrong interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   998
489c9b5090e2 Initial load
duke
parents:
diff changeset
   999
  if (type != T_ILLEGAL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1000
    interval->set_type(type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1001
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1002
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1003
  interval->add_range(from, to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1004
  interval->add_use_pos(to, use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1005
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1006
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1007
void LinearScan::add_temp(int reg_num, int temp_pos, IntervalUseKind use_kind, BasicType type) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1008
  Interval* interval = interval_at(reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1009
  if (interval == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1010
    interval = create_interval(reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1011
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1012
  assert(interval->reg_num() == reg_num, "wrong interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1013
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1014
  if (type != T_ILLEGAL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1015
    interval->set_type(type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1016
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1017
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1018
  interval->add_range(temp_pos, temp_pos + 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1019
  interval->add_use_pos(temp_pos, use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1020
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1021
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1022
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1023
// the results of this functions are used for optimizing spilling and reloading
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1024
// if the functions return shouldHaveRegister and the interval is spilled,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1025
// it is not reloaded to a register.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1026
IntervalUseKind LinearScan::use_kind_of_output_operand(LIR_Op* op, LIR_Opr opr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1027
  if (op->code() == lir_move) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1028
    assert(op->as_Op1() != NULL, "lir_move must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1029
    LIR_Op1* move = (LIR_Op1*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1030
    LIR_Opr res = move->result_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1031
    bool result_in_memory = res->is_virtual() && gen()->is_vreg_flag_set(res->vreg_number(), LIRGenerator::must_start_in_memory);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1032
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1033
    if (result_in_memory) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1034
      // Begin of an interval with must_start_in_memory set.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1035
      // This interval will always get a stack slot first, so return noUse.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1036
      return noUse;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1037
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1038
    } else if (move->in_opr()->is_stack()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1039
      // method argument (condition must be equal to handle_method_arguments)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1040
      return noUse;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1041
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1042
    } else if (move->in_opr()->is_register() && move->result_opr()->is_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1043
      // Move from register to register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1044
      if (block_of_op_with_id(op->id())->is_set(BlockBegin::osr_entry_flag)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1045
        // special handling of phi-function moves inside osr-entry blocks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1046
        // input operand must have a register instead of output operand (leads to better register allocation)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1047
        return shouldHaveRegister;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1048
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1049
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1050
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1051
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1052
  if (opr->is_virtual() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1053
      gen()->is_vreg_flag_set(opr->vreg_number(), LIRGenerator::must_start_in_memory)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1054
    // result is a stack-slot, so prevent immediate reloading
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1055
    return noUse;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1056
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1057
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1058
  // all other operands require a register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1059
  return mustHaveRegister;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1060
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1061
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1062
IntervalUseKind LinearScan::use_kind_of_input_operand(LIR_Op* op, LIR_Opr opr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1063
  if (op->code() == lir_move) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1064
    assert(op->as_Op1() != NULL, "lir_move must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1065
    LIR_Op1* move = (LIR_Op1*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1066
    LIR_Opr res = move->result_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1067
    bool result_in_memory = res->is_virtual() && gen()->is_vreg_flag_set(res->vreg_number(), LIRGenerator::must_start_in_memory);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1068
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1069
    if (result_in_memory) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1070
      // Move to an interval with must_start_in_memory set.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1071
      // To avoid moves from stack to stack (not allowed) force the input operand to a register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1072
      return mustHaveRegister;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1073
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1074
    } else if (move->in_opr()->is_register() && move->result_opr()->is_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1075
      // Move from register to register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1076
      if (block_of_op_with_id(op->id())->is_set(BlockBegin::osr_entry_flag)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1077
        // special handling of phi-function moves inside osr-entry blocks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1078
        // input operand must have a register instead of output operand (leads to better register allocation)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1079
        return mustHaveRegister;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1080
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1081
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1082
      // The input operand is not forced to a register (moves from stack to register are allowed),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1083
      // but it is faster if the input operand is in a register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1084
      return shouldHaveRegister;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1085
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1086
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1087
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1088
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  1089
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1090
  if (op->code() == lir_cmove) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1091
    // conditional moves can handle stack operands
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1092
    assert(op->result_opr()->is_register(), "result must always be in a register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1093
    return shouldHaveRegister;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1094
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1095
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1096
  // optimizations for second input operand of arithmehtic operations on Intel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1097
  // this operand is allowed to be on the stack in some cases
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1098
  BasicType opr_type = opr->type_register();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1099
  if (opr_type == T_FLOAT || opr_type == T_DOUBLE) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1100
    if ((UseSSE == 1 && opr_type == T_FLOAT) || UseSSE >= 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1101
      // SSE float instruction (T_DOUBLE only supported with SSE2)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1102
      switch (op->code()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1103
        case lir_cmp:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1104
        case lir_add:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1105
        case lir_sub:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1106
        case lir_mul:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1107
        case lir_div:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1108
        {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1109
          assert(op->as_Op2() != NULL, "must be LIR_Op2");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1110
          LIR_Op2* op2 = (LIR_Op2*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1111
          if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1112
            assert((op2->result_opr()->is_register() || op->code() == lir_cmp) && op2->in_opr1()->is_register(), "cannot mark second operand as stack if others are not in register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1113
            return shouldHaveRegister;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1114
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1115
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1116
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1117
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1118
      // FPU stack float instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1119
      switch (op->code()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1120
        case lir_add:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1121
        case lir_sub:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1122
        case lir_mul:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1123
        case lir_div:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1124
        {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1125
          assert(op->as_Op2() != NULL, "must be LIR_Op2");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1126
          LIR_Op2* op2 = (LIR_Op2*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1127
          if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1128
            assert((op2->result_opr()->is_register() || op->code() == lir_cmp) && op2->in_opr1()->is_register(), "cannot mark second operand as stack if others are not in register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1129
            return shouldHaveRegister;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1130
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1131
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1132
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1133
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1134
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1135
  } else if (opr_type != T_LONG) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1136
    // integer instruction (note: long operands must always be in register)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1137
    switch (op->code()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1138
      case lir_cmp:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1139
      case lir_add:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1140
      case lir_sub:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1141
      case lir_logic_and:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1142
      case lir_logic_or:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1143
      case lir_logic_xor:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1144
      {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1145
        assert(op->as_Op2() != NULL, "must be LIR_Op2");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1146
        LIR_Op2* op2 = (LIR_Op2*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1147
        if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1148
          assert((op2->result_opr()->is_register() || op->code() == lir_cmp) && op2->in_opr1()->is_register(), "cannot mark second operand as stack if others are not in register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1149
          return shouldHaveRegister;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1150
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1151
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1152
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1153
  }
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  1154
#endif // X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1155
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1156
  // all other operands require a register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1157
  return mustHaveRegister;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1158
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1159
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1160
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1161
void LinearScan::handle_method_arguments(LIR_Op* op) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1162
  // special handling for method arguments (moves from stack to virtual register):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1163
  // the interval gets no register assigned, but the stack slot.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1164
  // it is split before the first use by the register allocator.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1165
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1166
  if (op->code() == lir_move) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1167
    assert(op->as_Op1() != NULL, "must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1168
    LIR_Op1* move = (LIR_Op1*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1169
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1170
    if (move->in_opr()->is_stack()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1171
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1172
      int arg_size = compilation()->method()->arg_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1173
      LIR_Opr o = move->in_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1174
      if (o->is_single_stack()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1175
        assert(o->single_stack_ix() >= 0 && o->single_stack_ix() < arg_size, "out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1176
      } else if (o->is_double_stack()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1177
        assert(o->double_stack_ix() >= 0 && o->double_stack_ix() < arg_size, "out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1178
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1179
        ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1180
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1181
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1182
      assert(move->id() > 0, "invalid id");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1183
      assert(block_of_op_with_id(move->id())->number_of_preds() == 0, "move from stack must be in first block");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1184
      assert(move->result_opr()->is_virtual(), "result of move must be a virtual register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1185
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1186
      TRACE_LINEAR_SCAN(4, tty->print_cr("found move from stack slot %d to vreg %d", o->is_single_stack() ? o->single_stack_ix() : o->double_stack_ix(), reg_num(move->result_opr())));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1187
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1188
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1189
      Interval* interval = interval_at(reg_num(move->result_opr()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1190
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1191
      int stack_slot = LinearScan::nof_regs + (move->in_opr()->is_single_stack() ? move->in_opr()->single_stack_ix() : move->in_opr()->double_stack_ix());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1192
      interval->set_canonical_spill_slot(stack_slot);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1193
      interval->assign_reg(stack_slot);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1194
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1195
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1196
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1197
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1198
void LinearScan::handle_doubleword_moves(LIR_Op* op) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1199
  // special handling for doubleword move from memory to register:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1200
  // in this case the registers of the input address and the result
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1201
  // registers must not overlap -> add a temp range for the input registers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1202
  if (op->code() == lir_move) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1203
    assert(op->as_Op1() != NULL, "must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1204
    LIR_Op1* move = (LIR_Op1*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1205
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1206
    if (move->result_opr()->is_double_cpu() && move->in_opr()->is_pointer()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1207
      LIR_Address* address = move->in_opr()->as_address_ptr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1208
      if (address != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1209
        if (address->base()->is_valid()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1210
          add_temp(address->base(), op->id(), noUse);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1211
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1212
        if (address->index()->is_valid()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1213
          add_temp(address->index(), op->id(), noUse);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1214
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1215
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1216
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1217
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1218
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1219
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1220
void LinearScan::add_register_hints(LIR_Op* op) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1221
  switch (op->code()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1222
    case lir_move:      // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1223
    case lir_convert: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1224
      assert(op->as_Op1() != NULL, "lir_move, lir_convert must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1225
      LIR_Op1* move = (LIR_Op1*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1226
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1227
      LIR_Opr move_from = move->in_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1228
      LIR_Opr move_to = move->result_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1229
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1230
      if (move_to->is_register() && move_from->is_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1231
        Interval* from = interval_at(reg_num(move_from));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1232
        Interval* to = interval_at(reg_num(move_to));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1233
        if (from != NULL && to != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1234
          to->set_register_hint(from);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1235
          TRACE_LINEAR_SCAN(4, tty->print_cr("operation at op_id %d: added hint from interval %d to %d", move->id(), from->reg_num(), to->reg_num()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1236
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1237
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1238
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1239
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1240
    case lir_cmove: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1241
      assert(op->as_Op2() != NULL, "lir_cmove must be LIR_Op2");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1242
      LIR_Op2* cmove = (LIR_Op2*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1243
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1244
      LIR_Opr move_from = cmove->in_opr1();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1245
      LIR_Opr move_to = cmove->result_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1246
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1247
      if (move_to->is_register() && move_from->is_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1248
        Interval* from = interval_at(reg_num(move_from));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1249
        Interval* to = interval_at(reg_num(move_to));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1250
        if (from != NULL && to != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1251
          to->set_register_hint(from);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1252
          TRACE_LINEAR_SCAN(4, tty->print_cr("operation at op_id %d: added hint from interval %d to %d", cmove->id(), from->reg_num(), to->reg_num()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1253
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1254
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1255
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1256
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1257
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1258
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1259
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1260
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1261
void LinearScan::build_intervals() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1262
  TIME_LINEAR_SCAN(timer_build_intervals);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1263
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1264
  // initialize interval list with expected number of intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1265
  // (32 is added to have some space for split children without having to resize the list)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1266
  _intervals = IntervalList(num_virtual_regs() + 32);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1267
  // initialize all slots that are used by build_intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1268
  _intervals.at_put_grow(num_virtual_regs() - 1, NULL, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1269
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1270
  // create a list with all caller-save registers (cpu, fpu, xmm)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1271
  // when an instruction is a call, a temp range is created for all these registers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1272
  int num_caller_save_registers = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1273
  int caller_save_registers[LinearScan::nof_regs];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1274
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1275
  int i;
7427
d7b79a367474 6985015: C1 needs to support compressed oops
iveresov
parents: 7397
diff changeset
  1276
  for (i = 0; i < FrameMap::nof_caller_save_cpu_regs(); i++) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1277
    LIR_Opr opr = FrameMap::caller_save_cpu_reg_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1278
    assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1279
    assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1280
    caller_save_registers[num_caller_save_registers++] = reg_num(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1281
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1282
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1283
  // temp ranges for fpu registers are only created when the method has
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1284
  // virtual fpu operands. Otherwise no allocation for fpu registers is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1285
  // perfomed and so the temp ranges would be useless
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1286
  if (has_fpu_registers()) {
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  1287
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1288
    if (UseSSE < 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1289
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1290
      for (i = 0; i < FrameMap::nof_caller_save_fpu_regs; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1291
        LIR_Opr opr = FrameMap::caller_save_fpu_reg_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1292
        assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1293
        assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1294
        caller_save_registers[num_caller_save_registers++] = reg_num(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1295
      }
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  1296
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1297
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1298
    if (UseSSE > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1299
      for (i = 0; i < FrameMap::nof_caller_save_xmm_regs; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1300
        LIR_Opr opr = FrameMap::caller_save_xmm_reg_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1301
        assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1302
        assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1303
        caller_save_registers[num_caller_save_registers++] = reg_num(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1304
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1305
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1306
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1307
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1308
  assert(num_caller_save_registers <= LinearScan::nof_regs, "out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1309
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1310
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1311
  LIR_OpVisitState visitor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1312
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1313
  // iterate all blocks in reverse order
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1314
  for (i = block_count() - 1; i >= 0; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1315
    BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1316
    LIR_OpList* instructions = block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1317
    int         block_from =   block->first_lir_instruction_id();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1318
    int         block_to =     block->last_lir_instruction_id();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1319
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1320
    assert(block_from == instructions->at(0)->id(), "must be");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1321
    assert(block_to   == instructions->at(instructions->length() - 1)->id(), "must be");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1322
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1323
    // Update intervals for registers live at the end of this block;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1324
    BitMap live = block->live_out();
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  1325
    int size = (int)live.size();
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  1326
    for (int number = (int)live.get_next_one_offset(0, size); number < size; number = (int)live.get_next_one_offset(number + 1, size)) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1327
      assert(live.at(number), "should not stop here otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1328
      assert(number >= LIR_OprDesc::vreg_base, "fixed intervals must not be live on block bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1329
      TRACE_LINEAR_SCAN(2, tty->print_cr("live in %d to %d", number, block_to + 2));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1330
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1331
      add_use(number, block_from, block_to + 2, noUse, T_ILLEGAL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1332
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1333
      // add special use positions for loop-end blocks when the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1334
      // interval is used anywhere inside this loop.  It's possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1335
      // that the block was part of a non-natural loop, so it might
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1336
      // have an invalid loop index.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1337
      if (block->is_set(BlockBegin::linear_scan_loop_end_flag) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1338
          block->loop_index() != -1 &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1339
          is_interval_in_loop(number, block->loop_index())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1340
        interval_at(number)->add_use_pos(block_to + 1, loopEndMarker);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1341
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1342
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1343
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1344
    // iterate all instructions of the block in reverse order.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1345
    // skip the first instruction because it is always a label
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1346
    // definitions of intervals are processed before uses
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1347
    assert(visitor.no_operands(instructions->at(0)), "first operation must always be a label");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1348
    for (int j = instructions->length() - 1; j >= 1; j--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1349
      LIR_Op* op = instructions->at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1350
      int op_id = op->id();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1351
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1352
      // visit operation to collect all operands
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1353
      visitor.visit(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1354
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1355
      // add a temp range for each register if operation destroys caller-save registers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1356
      if (visitor.has_call()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1357
        for (int k = 0; k < num_caller_save_registers; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1358
          add_temp(caller_save_registers[k], op_id, noUse, T_ILLEGAL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1359
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1360
        TRACE_LINEAR_SCAN(4, tty->print_cr("operation destroys all caller-save registers"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1361
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1362
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1363
      // Add any platform dependent temps
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1364
      pd_add_temps(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1365
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1366
      // visit definitions (output and temp operands)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1367
      int k, n;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1368
      n = visitor.opr_count(LIR_OpVisitState::outputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1369
      for (k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1370
        LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1371
        assert(opr->is_register(), "visitor should only return register operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1372
        add_def(opr, op_id, use_kind_of_output_operand(op, opr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1373
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1374
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1375
      n = visitor.opr_count(LIR_OpVisitState::tempMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1376
      for (k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1377
        LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1378
        assert(opr->is_register(), "visitor should only return register operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1379
        add_temp(opr, op_id, mustHaveRegister);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1380
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1381
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1382
      // visit uses (input operands)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1383
      n = visitor.opr_count(LIR_OpVisitState::inputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1384
      for (k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1385
        LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1386
        assert(opr->is_register(), "visitor should only return register operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1387
        add_use(opr, block_from, op_id, use_kind_of_input_operand(op, opr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1388
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1389
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1390
      // Add uses of live locals from interpreter's point of view for proper
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1391
      // debug information generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1392
      // Treat these operands as temp values (if the life range is extended
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1393
      // to a call site, the value would be in a register at the call otherwise)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1394
      n = visitor.info_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1395
      for (k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1396
        CodeEmitInfo* info = visitor.info_at(k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1397
        ValueStack* stack = info->stack();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1398
        for_each_state_value(stack, value,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1399
          add_use(value, block_from, op_id + 1, noUse);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1400
        );
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1401
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1402
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1403
      // special steps for some instructions (especially moves)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1404
      handle_method_arguments(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1405
      handle_doubleword_moves(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1406
      add_register_hints(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1407
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1408
    } // end of instruction iteration
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1409
  } // end of block iteration
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1410
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1411
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1412
  // add the range [0, 1[ to all fixed intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1413
  // -> the register allocator need not handle unhandled fixed intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1414
  for (int n = 0; n < LinearScan::nof_regs; n++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1415
    Interval* interval = interval_at(n);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1416
    if (interval != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1417
      interval->add_range(0, 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1418
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1419
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1420
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1421
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1422
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1423
// ********** Phase 5: actual register allocation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1424
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1425
int LinearScan::interval_cmp(Interval** a, Interval** b) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1426
  if (*a != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1427
    if (*b != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1428
      return (*a)->from() - (*b)->from();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1429
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1430
      return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1431
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1432
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1433
    if (*b != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1434
      return 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1435
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1436
      return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1437
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1438
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1439
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1440
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1441
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1442
bool LinearScan::is_sorted(IntervalArray* intervals) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1443
  int from = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1444
  int i, j;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1445
  for (i = 0; i < intervals->length(); i ++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1446
    Interval* it = intervals->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1447
    if (it != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1448
      if (from > it->from()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1449
        assert(false, "");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1450
        return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1451
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1452
      from = it->from();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1453
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1454
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1455
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1456
  // check in both directions if sorted list and unsorted list contain same intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1457
  for (i = 0; i < interval_count(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1458
    if (interval_at(i) != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1459
      int num_found = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1460
      for (j = 0; j < intervals->length(); j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1461
        if (interval_at(i) == intervals->at(j)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1462
          num_found++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1463
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1464
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1465
      assert(num_found == 1, "lists do not contain same intervals");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1466
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1467
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1468
  for (j = 0; j < intervals->length(); j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1469
    int num_found = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1470
    for (i = 0; i < interval_count(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1471
      if (interval_at(i) == intervals->at(j)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1472
        num_found++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1473
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1474
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1475
    assert(num_found == 1, "lists do not contain same intervals");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1476
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1477
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1478
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1479
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1480
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1481
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1482
void LinearScan::add_to_list(Interval** first, Interval** prev, Interval* interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1483
  if (*prev != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1484
    (*prev)->set_next(interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1485
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1486
    *first = interval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1487
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1488
  *prev = interval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1489
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1490
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1491
void LinearScan::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
  1492
  assert(is_sorted(_sorted_intervals), "interval list is not sorted");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1493
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1494
  *list1 = *list2 = Interval::end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1495
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1496
  Interval* list1_prev = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1497
  Interval* list2_prev = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1498
  Interval* v;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1499
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1500
  const int n = _sorted_intervals->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1501
  for (int i = 0; i < n; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1502
    v = _sorted_intervals->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1503
    if (v == NULL) continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1504
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1505
    if (is_list1(v)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1506
      add_to_list(list1, &list1_prev, v);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1507
    } else if (is_list2 == NULL || is_list2(v)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1508
      add_to_list(list2, &list2_prev, v);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1509
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1510
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1511
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1512
  if (list1_prev != NULL) list1_prev->set_next(Interval::end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1513
  if (list2_prev != NULL) list2_prev->set_next(Interval::end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1514
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1515
  assert(list1_prev == NULL || list1_prev->next() == Interval::end(), "linear list ends not with sentinel");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1516
  assert(list2_prev == NULL || list2_prev->next() == Interval::end(), "linear list ends not with sentinel");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1517
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1518
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1519
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1520
void LinearScan::sort_intervals_before_allocation() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1521
  TIME_LINEAR_SCAN(timer_sort_intervals_before);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1522
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1523
  IntervalList* unsorted_list = &_intervals;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1524
  int unsorted_len = unsorted_list->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1525
  int sorted_len = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1526
  int unsorted_idx;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1527
  int sorted_idx = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1528
  int sorted_from_max = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1529
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1530
  // calc number of items for sorted list (sorted list must not contain NULL values)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1531
  for (unsorted_idx = 0; unsorted_idx < unsorted_len; unsorted_idx++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1532
    if (unsorted_list->at(unsorted_idx) != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1533
      sorted_len++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1534
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1535
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1536
  IntervalArray* sorted_list = new IntervalArray(sorted_len);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1537
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1538
  // special sorting algorithm: the original interval-list is almost sorted,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1539
  // only some intervals are swapped. So this is much faster than a complete QuickSort
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1540
  for (unsorted_idx = 0; unsorted_idx < unsorted_len; unsorted_idx++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1541
    Interval* cur_interval = unsorted_list->at(unsorted_idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1542
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1543
    if (cur_interval != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1544
      int cur_from = cur_interval->from();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1545
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1546
      if (sorted_from_max <= cur_from) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1547
        sorted_list->at_put(sorted_idx++, cur_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1548
        sorted_from_max = cur_interval->from();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1549
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1550
        // the asumption that the intervals are already sorted failed,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1551
        // so this interval must be sorted in manually
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1552
        int j;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1553
        for (j = sorted_idx - 1; j >= 0 && cur_from < sorted_list->at(j)->from(); j--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1554
          sorted_list->at_put(j + 1, sorted_list->at(j));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1555
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1556
        sorted_list->at_put(j + 1, cur_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1557
        sorted_idx++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1558
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1559
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1560
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1561
  _sorted_intervals = sorted_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1562
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1563
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1564
void LinearScan::sort_intervals_after_allocation() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1565
  TIME_LINEAR_SCAN(timer_sort_intervals_after);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1566
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1567
  IntervalArray* old_list      = _sorted_intervals;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1568
  IntervalList*  new_list      = _new_intervals_from_allocation;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1569
  int old_len = old_list->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1570
  int new_len = new_list->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1571
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1572
  if (new_len == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1573
    // no intervals have been added during allocation, so sorted list is already up to date
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1574
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1575
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1576
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1577
  // conventional sort-algorithm for new intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1578
  new_list->sort(interval_cmp);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1579
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1580
  // merge old and new list (both already sorted) into one combined list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1581
  IntervalArray* combined_list = new IntervalArray(old_len + new_len);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1582
  int old_idx = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1583
  int new_idx = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1584
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1585
  while (old_idx + new_idx < old_len + new_len) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1586
    if (new_idx >= new_len || (old_idx < old_len && old_list->at(old_idx)->from() <= new_list->at(new_idx)->from())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1587
      combined_list->at_put(old_idx + new_idx, old_list->at(old_idx));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1588
      old_idx++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1589
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1590
      combined_list->at_put(old_idx + new_idx, new_list->at(new_idx));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1591
      new_idx++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1592
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1593
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1594
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1595
  _sorted_intervals = combined_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1596
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1597
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1598
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1599
void LinearScan::allocate_registers() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1600
  TIME_LINEAR_SCAN(timer_allocate_registers);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1601
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1602
  Interval* precolored_cpu_intervals, *not_precolored_cpu_intervals;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1603
  Interval* precolored_fpu_intervals, *not_precolored_fpu_intervals;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1604
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1605
  create_unhandled_lists(&precolored_cpu_intervals, &not_precolored_cpu_intervals, is_precolored_cpu_interval, is_virtual_cpu_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1606
  if (has_fpu_registers()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1607
    create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1608
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1609
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1610
    // fpu register allocation is omitted because no virtual fpu registers are present
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1611
    // just check this again...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1612
    create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1613
    assert(not_precolored_fpu_intervals == Interval::end(), "missed an uncolored fpu interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1614
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1615
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1616
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1617
  // allocate cpu registers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1618
  LinearScanWalker cpu_lsw(this, precolored_cpu_intervals, not_precolored_cpu_intervals);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1619
  cpu_lsw.walk();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1620
  cpu_lsw.finish_allocation();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1621
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1622
  if (has_fpu_registers()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1623
    // allocate fpu registers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1624
    LinearScanWalker fpu_lsw(this, precolored_fpu_intervals, not_precolored_fpu_intervals);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1625
    fpu_lsw.walk();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1626
    fpu_lsw.finish_allocation();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1627
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1628
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1629
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1630
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1631
// ********** Phase 6: resolve data flow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1632
// (insert moves at edges between blocks if intervals have been split)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1633
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1634
// wrapper for Interval::split_child_at_op_id that performs a bailout in product mode
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1635
// instead of returning NULL
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1636
Interval* LinearScan::split_child_at_op_id(Interval* interval, int op_id, LIR_OpVisitState::OprMode mode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1637
  Interval* result = interval->split_child_at_op_id(op_id, mode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1638
  if (result != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1639
    return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1640
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1641
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1642
  assert(false, "must find an interval, but do a clean bailout in product mode");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1643
  result = new Interval(LIR_OprDesc::vreg_base);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1644
  result->assign_reg(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1645
  result->set_type(T_INT);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1646
  BAILOUT_("LinearScan: interval is NULL", result);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1647
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1648
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1649
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1650
Interval* LinearScan::interval_at_block_begin(BlockBegin* block, int reg_num) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1651
  assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1652
  assert(interval_at(reg_num) != NULL, "no interval found");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1653
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1654
  return split_child_at_op_id(interval_at(reg_num), block->first_lir_instruction_id(), LIR_OpVisitState::outputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1655
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1656
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1657
Interval* LinearScan::interval_at_block_end(BlockBegin* block, int reg_num) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1658
  assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1659
  assert(interval_at(reg_num) != NULL, "no interval found");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1660
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1661
  return split_child_at_op_id(interval_at(reg_num), block->last_lir_instruction_id() + 1, LIR_OpVisitState::outputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1662
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1663
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1664
Interval* LinearScan::interval_at_op_id(int reg_num, int op_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1665
  assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1666
  assert(interval_at(reg_num) != NULL, "no interval found");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1667
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1668
  return split_child_at_op_id(interval_at(reg_num), op_id, LIR_OpVisitState::inputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1669
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1670
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1671
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1672
void LinearScan::resolve_collect_mappings(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1673
  DEBUG_ONLY(move_resolver.check_empty());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1674
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1675
  const int num_regs = num_virtual_regs();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1676
  const int size = live_set_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1677
  const BitMap live_at_edge = to_block->live_in();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1678
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1679
  // visit all registers where the live_at_edge bit is set
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  1680
  for (int r = (int)live_at_edge.get_next_one_offset(0, size); r < size; r = (int)live_at_edge.get_next_one_offset(r + 1, size)) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1681
    assert(r < num_regs, "live information set for not exisiting interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1682
    assert(from_block->live_out().at(r) && to_block->live_in().at(r), "interval not live at this edge");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1683
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1684
    Interval* from_interval = interval_at_block_end(from_block, r);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1685
    Interval* to_interval = interval_at_block_begin(to_block, r);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1686
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1687
    if (from_interval != to_interval && (from_interval->assigned_reg() != to_interval->assigned_reg() || from_interval->assigned_regHi() != to_interval->assigned_regHi())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1688
      // need to insert move instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1689
      move_resolver.add_mapping(from_interval, to_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1690
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1691
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1692
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1693
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1694
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1695
void LinearScan::resolve_find_insert_pos(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1696
  if (from_block->number_of_sux() <= 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1697
    TRACE_LINEAR_SCAN(4, tty->print_cr("inserting moves at end of from_block B%d", from_block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1698
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1699
    LIR_OpList* instructions = from_block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1700
    LIR_OpBranch* branch = instructions->last()->as_OpBranch();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1701
    if (branch != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1702
      // insert moves before branch
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1703
      assert(branch->cond() == lir_cond_always, "block does not end with an unconditional jump");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1704
      move_resolver.set_insert_position(from_block->lir(), instructions->length() - 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1705
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1706
      move_resolver.set_insert_position(from_block->lir(), instructions->length() - 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1707
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1708
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1709
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1710
    TRACE_LINEAR_SCAN(4, tty->print_cr("inserting moves at beginning of to_block B%d", to_block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1711
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1712
    assert(from_block->lir()->instructions_list()->at(0)->as_OpLabel() != NULL, "block does not start with a label");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1713
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1714
    // because the number of predecessor edges matches the number of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1715
    // successor edges, blocks which are reached by switch statements
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1716
    // may have be more than one predecessor but it will be guaranteed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1717
    // that all predecessors will be the same.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1718
    for (int i = 0; i < to_block->number_of_preds(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1719
      assert(from_block == to_block->pred_at(i), "all critical edges must be broken");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1720
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1721
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1722
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1723
    move_resolver.set_insert_position(to_block->lir(), 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1724
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1725
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1726
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1727
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1728
// insert necessary moves (spilling or reloading) at edges between blocks if interval has been split
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1729
void LinearScan::resolve_data_flow() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1730
  TIME_LINEAR_SCAN(timer_resolve_data_flow);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1731
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1732
  int num_blocks = block_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1733
  MoveResolver move_resolver(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1734
  BitMap block_completed(num_blocks);  block_completed.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1735
  BitMap already_resolved(num_blocks); already_resolved.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1736
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1737
  int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1738
  for (i = 0; i < num_blocks; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1739
    BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1740
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1741
    // check if block has only one predecessor and only one successor
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1742
    if (block->number_of_preds() == 1 && block->number_of_sux() == 1 && block->number_of_exception_handlers() == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1743
      LIR_OpList* instructions = block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1744
      assert(instructions->at(0)->code() == lir_label, "block must start with label");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1745
      assert(instructions->last()->code() == lir_branch, "block with successors must end with branch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1746
      assert(instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block with successor must end with unconditional branch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1747
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1748
      // check if block is empty (only label and branch)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1749
      if (instructions->length() == 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1750
        BlockBegin* pred = block->pred_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1751
        BlockBegin* sux = block->sux_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1752
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1753
        // prevent optimization of two consecutive blocks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1754
        if (!block_completed.at(pred->linear_scan_number()) && !block_completed.at(sux->linear_scan_number())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1755
          TRACE_LINEAR_SCAN(3, tty->print_cr("**** optimizing empty block B%d (pred: B%d, sux: B%d)", block->block_id(), pred->block_id(), sux->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1756
          block_completed.set_bit(block->linear_scan_number());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1757
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1758
          // directly resolve between pred and sux (without looking at the empty block between)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1759
          resolve_collect_mappings(pred, sux, move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1760
          if (move_resolver.has_mappings()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1761
            move_resolver.set_insert_position(block->lir(), 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1762
            move_resolver.resolve_and_append_moves();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1763
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1764
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1765
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1766
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1767
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1768
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1769
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1770
  for (i = 0; i < num_blocks; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1771
    if (!block_completed.at(i)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1772
      BlockBegin* from_block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1773
      already_resolved.set_from(block_completed);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1774
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1775
      int num_sux = from_block->number_of_sux();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1776
      for (int s = 0; s < num_sux; s++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1777
        BlockBegin* to_block = from_block->sux_at(s);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1778
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1779
        // check for duplicate edges between the same blocks (can happen with switch blocks)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1780
        if (!already_resolved.at(to_block->linear_scan_number())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1781
          TRACE_LINEAR_SCAN(3, tty->print_cr("**** processing edge between B%d and B%d", from_block->block_id(), to_block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1782
          already_resolved.set_bit(to_block->linear_scan_number());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1783
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1784
          // collect all intervals that have been split between from_block and to_block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1785
          resolve_collect_mappings(from_block, to_block, move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1786
          if (move_resolver.has_mappings()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1787
            resolve_find_insert_pos(from_block, to_block, move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1788
            move_resolver.resolve_and_append_moves();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1789
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1790
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1791
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1792
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1793
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1794
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1795
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1796
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1797
void LinearScan::resolve_exception_entry(BlockBegin* block, int reg_num, MoveResolver &move_resolver) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1798
  if (interval_at(reg_num) == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1799
    // if a phi function is never used, no interval is created -> ignore this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1800
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1801
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1802
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1803
  Interval* interval = interval_at_block_begin(block, reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1804
  int reg = interval->assigned_reg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1805
  int regHi = interval->assigned_regHi();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1806
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1807
  if ((reg < nof_regs && interval->always_in_memory()) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1808
      (use_fpu_stack_allocation() && reg >= pd_first_fpu_reg && reg <= pd_last_fpu_reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1809
    // the interval is split to get a short range that is located on the stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1810
    // in the following two cases:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1811
    // * the interval started in memory (e.g. method parameter), but is currently in a register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1812
    //   this is an optimization for exception handling that reduces the number of moves that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1813
    //   are necessary for resolving the states when an exception uses this exception handler
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1814
    // * the interval would be on the fpu stack at the begin of the exception handler
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1815
    //   this is not allowed because of the complicated fpu stack handling on Intel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1816
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1817
    // range that will be spilled to memory
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1818
    int from_op_id = block->first_lir_instruction_id();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1819
    int to_op_id = from_op_id + 1;  // short live range of length 1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1820
    assert(interval->from() <= from_op_id && interval->to() >= to_op_id,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1821
           "no split allowed between exception entry and first instruction");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1822
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1823
    if (interval->from() != from_op_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1824
      // the part before from_op_id is unchanged
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1825
      interval = interval->split(from_op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1826
      interval->assign_reg(reg, regHi);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1827
      append_interval(interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1828
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1829
    assert(interval->from() == from_op_id, "must be true now");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1830
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1831
    Interval* spilled_part = interval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1832
    if (interval->to() != to_op_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1833
      // the part after to_op_id is unchanged
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1834
      spilled_part = interval->split_from_start(to_op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1835
      append_interval(spilled_part);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1836
      move_resolver.add_mapping(spilled_part, interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1837
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1838
    assign_spill_slot(spilled_part);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1839
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1840
    assert(spilled_part->from() == from_op_id && spilled_part->to() == to_op_id, "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1841
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1842
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1843
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1844
void LinearScan::resolve_exception_entry(BlockBegin* block, MoveResolver &move_resolver) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1845
  assert(block->is_set(BlockBegin::exception_entry_flag), "should not call otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1846
  DEBUG_ONLY(move_resolver.check_empty());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1847
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1848
  // visit all registers where the live_in bit is set
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1849
  int size = live_set_size();
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  1850
  for (int r = (int)block->live_in().get_next_one_offset(0, size); r < size; r = (int)block->live_in().get_next_one_offset(r + 1, size)) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1851
    resolve_exception_entry(block, r, move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1852
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1853
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1854
  // the live_in bits are not set for phi functions of the xhandler entry, so iterate them separately
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1855
  for_each_phi_fun(block, phi,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1856
    resolve_exception_entry(block, phi->operand()->vreg_number(), move_resolver)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1857
  );
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1858
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1859
  if (move_resolver.has_mappings()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1860
    // insert moves after first instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1861
    move_resolver.set_insert_position(block->lir(), 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1862
    move_resolver.resolve_and_append_moves();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1863
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1864
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1865
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1866
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1867
void LinearScan::resolve_exception_edge(XHandler* handler, int throwing_op_id, int reg_num, Phi* phi, MoveResolver &move_resolver) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1868
  if (interval_at(reg_num) == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1869
    // if a phi function is never used, no interval is created -> ignore this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1870
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1871
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1872
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1873
  // the computation of to_interval is equal to resolve_collect_mappings,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1874
  // but from_interval is more complicated because of phi functions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1875
  BlockBegin* to_block = handler->entry_block();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1876
  Interval* to_interval = interval_at_block_begin(to_block, reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1877
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1878
  if (phi != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1879
    // phi function of the exception entry block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1880
    // no moves are created for this phi function in the LIR_Generator, so the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1881
    // interval at the throwing instruction must be searched using the operands
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1882
    // of the phi function
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1883
    Value from_value = phi->operand_at(handler->phi_operand());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1884
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1885
    // with phi functions it can happen that the same from_value is used in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1886
    // multiple mappings, so notify move-resolver that this is allowed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1887
    move_resolver.set_multiple_reads_allowed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1888
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1889
    Constant* con = from_value->as_Constant();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1890
    if (con != NULL && !con->is_pinned()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1891
      // unpinned constants may have no register, so add mapping from constant to interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1892
      move_resolver.add_mapping(LIR_OprFact::value_type(con->type()), to_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1893
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1894
      // search split child at the throwing op_id
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1895
      Interval* from_interval = interval_at_op_id(from_value->operand()->vreg_number(), throwing_op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1896
      move_resolver.add_mapping(from_interval, to_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1897
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1898
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1899
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1900
    // no phi function, so use reg_num also for from_interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1901
    // search split child at the throwing op_id
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1902
    Interval* from_interval = interval_at_op_id(reg_num, throwing_op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1903
    if (from_interval != to_interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1904
      // optimization to reduce number of moves: when to_interval is on stack and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1905
      // the stack slot is known to be always correct, then no move is necessary
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1906
      if (!from_interval->always_in_memory() || from_interval->canonical_spill_slot() != to_interval->assigned_reg()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1907
        move_resolver.add_mapping(from_interval, to_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1908
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1909
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1910
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1911
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1912
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1913
void LinearScan::resolve_exception_edge(XHandler* handler, int throwing_op_id, MoveResolver &move_resolver) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1914
  TRACE_LINEAR_SCAN(4, tty->print_cr("resolving exception handler B%d: throwing_op_id=%d", handler->entry_block()->block_id(), throwing_op_id));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1915
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1916
  DEBUG_ONLY(move_resolver.check_empty());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1917
  assert(handler->lir_op_id() == -1, "already processed this xhandler");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1918
  DEBUG_ONLY(handler->set_lir_op_id(throwing_op_id));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1919
  assert(handler->entry_code() == NULL, "code already present");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1920
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1921
  // visit all registers where the live_in bit is set
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1922
  BlockBegin* block = handler->entry_block();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1923
  int size = live_set_size();
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  1924
  for (int r = (int)block->live_in().get_next_one_offset(0, size); r < size; r = (int)block->live_in().get_next_one_offset(r + 1, size)) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1925
    resolve_exception_edge(handler, throwing_op_id, r, NULL, move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1926
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1927
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1928
  // the live_in bits are not set for phi functions of the xhandler entry, so iterate them separately
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1929
  for_each_phi_fun(block, phi,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1930
    resolve_exception_edge(handler, throwing_op_id, phi->operand()->vreg_number(), phi, move_resolver)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1931
  );
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1932
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1933
  if (move_resolver.has_mappings()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1934
    LIR_List* entry_code = new LIR_List(compilation());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1935
    move_resolver.set_insert_position(entry_code, 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1936
    move_resolver.resolve_and_append_moves();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1937
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1938
    entry_code->jump(handler->entry_block());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1939
    handler->set_entry_code(entry_code);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1940
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1941
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1942
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1943
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1944
void LinearScan::resolve_exception_handlers() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1945
  MoveResolver move_resolver(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1946
  LIR_OpVisitState visitor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1947
  int num_blocks = block_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1948
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1949
  int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1950
  for (i = 0; i < num_blocks; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1951
    BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1952
    if (block->is_set(BlockBegin::exception_entry_flag)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1953
      resolve_exception_entry(block, move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1954
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1955
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1956
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1957
  for (i = 0; i < num_blocks; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1958
    BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1959
    LIR_List* ops = block->lir();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1960
    int num_ops = ops->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1961
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1962
    // iterate all instructions of the block. skip the first because it is always a label
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1963
    assert(visitor.no_operands(ops->at(0)), "first operation must always be a label");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1964
    for (int j = 1; j < num_ops; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1965
      LIR_Op* op = ops->at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1966
      int op_id = op->id();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1967
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1968
      if (op_id != -1 && has_info(op_id)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1969
        // visit operation to collect all operands
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1970
        visitor.visit(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1971
        assert(visitor.info_count() > 0, "should not visit otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1972
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1973
        XHandlers* xhandlers = visitor.all_xhandler();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1974
        int n = xhandlers->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1975
        for (int k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1976
          resolve_exception_edge(xhandlers->handler_at(k), op_id, move_resolver);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1977
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1978
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1979
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1980
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1981
        visitor.visit(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1982
        assert(visitor.all_xhandler()->length() == 0, "missed exception handler");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1983
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1984
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1985
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1986
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1987
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1988
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1989
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1990
// ********** Phase 7: assign register numbers back to LIR
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1991
// (includes computation of debug information and oop maps)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1992
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1993
VMReg LinearScan::vm_reg_for_interval(Interval* interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1994
  VMReg reg = interval->cached_vm_reg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1995
  if (!reg->is_valid() ) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1996
    reg = vm_reg_for_operand(operand_for_interval(interval));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1997
    interval->set_cached_vm_reg(reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1998
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1999
  assert(reg == vm_reg_for_operand(operand_for_interval(interval)), "wrong cached value");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2000
  return reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2001
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2002
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2003
VMReg LinearScan::vm_reg_for_operand(LIR_Opr opr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2004
  assert(opr->is_oop(), "currently only implemented for oop operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2005
  return frame_map()->regname(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2006
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2007
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2008
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2009
LIR_Opr LinearScan::operand_for_interval(Interval* interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2010
  LIR_Opr opr = interval->cached_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2011
  if (opr->is_illegal()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2012
    opr = calc_operand_for_interval(interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2013
    interval->set_cached_opr(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2014
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2015
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2016
  assert(opr == calc_operand_for_interval(interval), "wrong cached value");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2017
  return opr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2018
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2019
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2020
LIR_Opr LinearScan::calc_operand_for_interval(const Interval* interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2021
  int assigned_reg = interval->assigned_reg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2022
  BasicType type = interval->type();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2023
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2024
  if (assigned_reg >= nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2025
    // stack slot
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2026
    assert(interval->assigned_regHi() == any_reg, "must not have hi register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2027
    return LIR_OprFact::stack(assigned_reg - nof_regs, type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2028
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2029
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2030
    // register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2031
    switch (type) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2032
      case T_OBJECT: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2033
        assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2034
        assert(interval->assigned_regHi() == any_reg, "must not have hi register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2035
        return LIR_OprFact::single_cpu_oop(assigned_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2036
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2037
6742
81ef369b8fc7 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 6176
diff changeset
  2038
      case T_ADDRESS: {
81ef369b8fc7 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 6176
diff changeset
  2039
        assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
81ef369b8fc7 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 6176
diff changeset
  2040
        assert(interval->assigned_regHi() == any_reg, "must not have hi register");
81ef369b8fc7 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 6176
diff changeset
  2041
        return LIR_OprFact::single_cpu_address(assigned_reg);
81ef369b8fc7 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 6176
diff changeset
  2042
      }
81ef369b8fc7 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 6176
diff changeset
  2043
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2044
#ifdef __SOFTFP__
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2045
      case T_FLOAT:  // fall through
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2046
#endif // __SOFTFP__
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2047
      case T_INT: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2048
        assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2049
        assert(interval->assigned_regHi() == any_reg, "must not have hi register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2050
        return LIR_OprFact::single_cpu(assigned_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2051
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2052
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2053
#ifdef __SOFTFP__
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2054
      case T_DOUBLE:  // fall through
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2055
#endif // __SOFTFP__
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2056
      case T_LONG: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2057
        int assigned_regHi = interval->assigned_regHi();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2058
        assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2059
        assert(num_physical_regs(T_LONG) == 1 ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2060
               (assigned_regHi >= pd_first_cpu_reg && assigned_regHi <= pd_last_cpu_reg), "no cpu register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2061
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2062
        assert(assigned_reg != assigned_regHi, "invalid allocation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2063
        assert(num_physical_regs(T_LONG) == 1 || assigned_reg < assigned_regHi,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2064
               "register numbers must be sorted (ensure that e.g. a move from eax,ebx to ebx,eax can not occur)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2065
        assert((assigned_regHi != any_reg) ^ (num_physical_regs(T_LONG) == 1), "must be match");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2066
        if (requires_adjacent_regs(T_LONG)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2067
          assert(assigned_reg % 2 == 0 && assigned_reg + 1 == assigned_regHi, "must be sequential and even");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2068
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2069
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2070
#ifdef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2071
        return LIR_OprFact::double_cpu(assigned_reg, assigned_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2072
#else
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2073
#if defined(SPARC) || defined(PPC)
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2074
        return LIR_OprFact::double_cpu(assigned_regHi, assigned_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2075
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2076
        return LIR_OprFact::double_cpu(assigned_reg, assigned_regHi);
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2077
#endif // SPARC
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2078
#endif // LP64
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2079
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2080
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2081
#ifndef __SOFTFP__
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2082
      case T_FLOAT: {
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2083
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2084
        if (UseSSE >= 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2085
          assert(assigned_reg >= pd_first_xmm_reg && assigned_reg <= pd_last_xmm_reg, "no xmm register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2086
          assert(interval->assigned_regHi() == any_reg, "must not have hi register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2087
          return LIR_OprFact::single_xmm(assigned_reg - pd_first_xmm_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2088
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2089
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2090
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2091
        assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2092
        assert(interval->assigned_regHi() == any_reg, "must not have hi register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2093
        return LIR_OprFact::single_fpu(assigned_reg - pd_first_fpu_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2094
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2095
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2096
      case T_DOUBLE: {
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2097
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2098
        if (UseSSE >= 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2099
          assert(assigned_reg >= pd_first_xmm_reg && assigned_reg <= pd_last_xmm_reg, "no xmm register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2100
          assert(interval->assigned_regHi() == any_reg, "must not have hi register (double xmm values are stored in one register)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2101
          return LIR_OprFact::double_xmm(assigned_reg - pd_first_xmm_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2102
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2103
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2104
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2105
#ifdef SPARC
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2106
        assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2107
        assert(interval->assigned_regHi() >= pd_first_fpu_reg && interval->assigned_regHi() <= pd_last_fpu_reg, "no fpu register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2108
        assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2109
        LIR_Opr result = LIR_OprFact::double_fpu(interval->assigned_regHi() - pd_first_fpu_reg, assigned_reg - pd_first_fpu_reg);
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2110
#elif defined(ARM)
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2111
        assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2112
        assert(interval->assigned_regHi() >= pd_first_fpu_reg && interval->assigned_regHi() <= pd_last_fpu_reg, "no fpu register");
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2113
        assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even");
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2114
        LIR_Opr result = LIR_OprFact::double_fpu(assigned_reg - pd_first_fpu_reg, interval->assigned_regHi() - pd_first_fpu_reg);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2115
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2116
        assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2117
        assert(interval->assigned_regHi() == any_reg, "must not have hi register (double fpu values are stored in one register on Intel)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2118
        LIR_Opr result = LIR_OprFact::double_fpu(assigned_reg - pd_first_fpu_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2119
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2120
        return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2121
      }
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2122
#endif // __SOFTFP__
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2123
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2124
      default: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2125
        ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2126
        return LIR_OprFact::illegalOpr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2127
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2128
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2129
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2130
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2131
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2132
LIR_Opr LinearScan::canonical_spill_opr(Interval* interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2133
  assert(interval->canonical_spill_slot() >= nof_regs, "canonical spill slot not set");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2134
  return LIR_OprFact::stack(interval->canonical_spill_slot() - nof_regs, interval->type());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2135
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2136
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2137
LIR_Opr LinearScan::color_lir_opr(LIR_Opr opr, int op_id, LIR_OpVisitState::OprMode mode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2138
  assert(opr->is_virtual(), "should not call this otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2139
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2140
  Interval* interval = interval_at(opr->vreg_number());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2141
  assert(interval != NULL, "interval must exist");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2142
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2143
  if (op_id != -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2144
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2145
    BlockBegin* block = block_of_op_with_id(op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2146
    if (block->number_of_sux() <= 1 && op_id == block->last_lir_instruction_id()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2147
      // check if spill moves could have been appended at the end of this block, but
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2148
      // before the branch instruction. So the split child information for this branch would
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2149
      // be incorrect.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2150
      LIR_OpBranch* branch = block->lir()->instructions_list()->last()->as_OpBranch();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2151
      if (branch != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2152
        if (block->live_out().at(opr->vreg_number())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2153
          assert(branch->cond() == lir_cond_always, "block does not end with an unconditional jump");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2154
          assert(false, "can't get split child for the last branch of a block because the information would be incorrect (moves are inserted before the branch in resolve_data_flow)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2155
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2156
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2157
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2158
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2159
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2160
    // operands are not changed when an interval is split during allocation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2161
    // so search the right interval here
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2162
    interval = split_child_at_op_id(interval, op_id, mode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2163
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2164
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2165
  LIR_Opr res = operand_for_interval(interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2166
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2167
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2168
  // new semantic for is_last_use: not only set on definite end of interval,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2169
  // but also before hole
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2170
  // This may still miss some cases (e.g. for dead values), but it is not necessary that the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2171
  // last use information is completely correct
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2172
  // information is only needed for fpu stack allocation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2173
  if (res->is_fpu_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2174
    if (opr->is_last_use() || op_id == interval->to() || (op_id != -1 && interval->has_hole_between(op_id, op_id + 1))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2175
      assert(op_id == -1 || !is_block_begin(op_id), "holes at begin of block may also result from control flow");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2176
      res = res->make_last_use();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2177
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2178
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2179
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2180
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2181
  assert(!gen()->is_vreg_flag_set(opr->vreg_number(), LIRGenerator::callee_saved) || !FrameMap::is_caller_save_register(res), "bad allocation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2182
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2183
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2184
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2185
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2186
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2187
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2188
// some methods used to check correctness of debug information
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2189
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2190
void assert_no_register_values(GrowableArray<ScopeValue*>* values) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2191
  if (values == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2192
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2193
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2194
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2195
  for (int i = 0; i < values->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2196
    ScopeValue* value = values->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2197
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2198
    if (value->is_location()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2199
      Location location = ((LocationValue*)value)->location();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2200
      assert(location.where() == Location::on_stack, "value is in register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2201
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2202
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2203
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2204
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2205
void assert_no_register_values(GrowableArray<MonitorValue*>* values) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2206
  if (values == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2207
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2208
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2209
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2210
  for (int i = 0; i < values->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2211
    MonitorValue* value = values->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2212
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2213
    if (value->owner()->is_location()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2214
      Location location = ((LocationValue*)value->owner())->location();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2215
      assert(location.where() == Location::on_stack, "owner is in register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2216
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2217
    assert(value->basic_lock().where() == Location::on_stack, "basic_lock is in register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2218
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2219
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2220
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2221
void assert_equal(Location l1, Location l2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2222
  assert(l1.where() == l2.where() && l1.type() == l2.type() && l1.offset() == l2.offset(), "");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2223
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2224
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2225
void assert_equal(ScopeValue* v1, ScopeValue* v2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2226
  if (v1->is_location()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2227
    assert(v2->is_location(), "");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2228
    assert_equal(((LocationValue*)v1)->location(), ((LocationValue*)v2)->location());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2229
  } else if (v1->is_constant_int()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2230
    assert(v2->is_constant_int(), "");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2231
    assert(((ConstantIntValue*)v1)->value() == ((ConstantIntValue*)v2)->value(), "");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2232
  } else if (v1->is_constant_double()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2233
    assert(v2->is_constant_double(), "");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2234
    assert(((ConstantDoubleValue*)v1)->value() == ((ConstantDoubleValue*)v2)->value(), "");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2235
  } else if (v1->is_constant_long()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2236
    assert(v2->is_constant_long(), "");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2237
    assert(((ConstantLongValue*)v1)->value() == ((ConstantLongValue*)v2)->value(), "");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2238
  } else if (v1->is_constant_oop()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2239
    assert(v2->is_constant_oop(), "");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2240
    assert(((ConstantOopWriteValue*)v1)->value() == ((ConstantOopWriteValue*)v2)->value(), "");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2241
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2242
    ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2243
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2244
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2245
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2246
void assert_equal(MonitorValue* m1, MonitorValue* m2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2247
  assert_equal(m1->owner(), m2->owner());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2248
  assert_equal(m1->basic_lock(), m2->basic_lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2249
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2250
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2251
void assert_equal(IRScopeDebugInfo* d1, IRScopeDebugInfo* d2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2252
  assert(d1->scope() == d2->scope(), "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2253
  assert(d1->bci() == d2->bci(), "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2254
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2255
  if (d1->locals() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2256
    assert(d1->locals() != NULL && d2->locals() != NULL, "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2257
    assert(d1->locals()->length() == d2->locals()->length(), "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2258
    for (int i = 0; i < d1->locals()->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2259
      assert_equal(d1->locals()->at(i), d2->locals()->at(i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2260
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2261
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2262
    assert(d1->locals() == NULL && d2->locals() == NULL, "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2263
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2264
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2265
  if (d1->expressions() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2266
    assert(d1->expressions() != NULL && d2->expressions() != NULL, "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2267
    assert(d1->expressions()->length() == d2->expressions()->length(), "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2268
    for (int i = 0; i < d1->expressions()->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2269
      assert_equal(d1->expressions()->at(i), d2->expressions()->at(i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2270
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2271
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2272
    assert(d1->expressions() == NULL && d2->expressions() == NULL, "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2273
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2274
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2275
  if (d1->monitors() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2276
    assert(d1->monitors() != NULL && d2->monitors() != NULL, "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2277
    assert(d1->monitors()->length() == d2->monitors()->length(), "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2278
    for (int i = 0; i < d1->monitors()->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2279
      assert_equal(d1->monitors()->at(i), d2->monitors()->at(i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2280
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2281
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2282
    assert(d1->monitors() == NULL && d2->monitors() == NULL, "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2283
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2284
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2285
  if (d1->caller() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2286
    assert(d1->caller() != NULL && d2->caller() != NULL, "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2287
    assert_equal(d1->caller(), d2->caller());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2288
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2289
    assert(d1->caller() == NULL && d2->caller() == NULL, "not equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2290
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2291
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2292
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2293
void check_stack_depth(CodeEmitInfo* info, int stack_end) {
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2294
  if (info->stack()->bci() != SynchronizationEntryBCI && !info->scope()->method()->is_native()) {
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2295
    Bytecodes::Code code = info->scope()->method()->java_code_at_bci(info->stack()->bci());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2296
    switch (code) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2297
      case Bytecodes::_ifnull    : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2298
      case Bytecodes::_ifnonnull : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2299
      case Bytecodes::_ifeq      : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2300
      case Bytecodes::_ifne      : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2301
      case Bytecodes::_iflt      : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2302
      case Bytecodes::_ifge      : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2303
      case Bytecodes::_ifgt      : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2304
      case Bytecodes::_ifle      : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2305
      case Bytecodes::_if_icmpeq : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2306
      case Bytecodes::_if_icmpne : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2307
      case Bytecodes::_if_icmplt : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2308
      case Bytecodes::_if_icmpge : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2309
      case Bytecodes::_if_icmpgt : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2310
      case Bytecodes::_if_icmple : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2311
      case Bytecodes::_if_acmpeq : // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2312
      case Bytecodes::_if_acmpne :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2313
        assert(stack_end >= -Bytecodes::depth(code), "must have non-empty expression stack at if bytecode");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2314
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2315
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2316
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2317
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2318
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2319
#endif // ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2320
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2321
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2322
IntervalWalker* LinearScan::init_compute_oop_maps() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2323
  // setup lists of potential oops for walking
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2324
  Interval* oop_intervals;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2325
  Interval* non_oop_intervals;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2326
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2327
  create_unhandled_lists(&oop_intervals, &non_oop_intervals, is_oop_interval, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2328
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2329
  // intervals that have no oops inside need not to be processed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2330
  // to ensure a walking until the last instruction id, add a dummy interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2331
  // with a high operation id
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2332
  non_oop_intervals = new Interval(any_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2333
  non_oop_intervals->add_range(max_jint - 2, max_jint - 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2334
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2335
  return new IntervalWalker(this, oop_intervals, non_oop_intervals);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2336
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2337
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2338
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2339
OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo* info, bool is_call_site) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2340
  TRACE_LINEAR_SCAN(3, tty->print_cr("creating oop map at op_id %d", op->id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2341
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2342
  // walk before the current operation -> intervals that start at
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2343
  // the operation (= output operands of the operation) are not
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2344
  // included in the oop map
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2345
  iw->walk_before(op->id());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2346
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2347
  int frame_size = frame_map()->framesize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2348
  int arg_count = frame_map()->oop_map_arg_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2349
  OopMap* map = new OopMap(frame_size, arg_count);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2350
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2351
  // Check if this is a patch site.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2352
  bool is_patch_info = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2353
  if (op->code() == lir_move) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2354
    assert(!is_call_site, "move must not be a call site");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2355
    assert(op->as_Op1() != NULL, "move must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2356
    LIR_Op1* move = (LIR_Op1*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2357
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2358
    is_patch_info = move->patch_code() != lir_patch_none;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2359
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2360
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2361
  // Iterate through active intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2362
  for (Interval* interval = iw->active_first(fixedKind); interval != Interval::end(); interval = interval->next()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2363
    int assigned_reg = interval->assigned_reg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2364
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2365
    assert(interval->current_from() <= op->id() && op->id() <= interval->current_to(), "interval should not be active otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2366
    assert(interval->assigned_regHi() == any_reg, "oop must be single word");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2367
    assert(interval->reg_num() >= LIR_OprDesc::vreg_base, "fixed interval found");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2368
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2369
    // Check if this range covers the instruction. Intervals that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2370
    // start or end at the current operation are not included in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2371
    // oop map, except in the case of patching moves.  For patching
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2372
    // moves, any intervals which end at this instruction are included
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2373
    // in the oop map since we may safepoint while doing the patch
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2374
    // before we've consumed the inputs.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2375
    if (is_patch_info || op->id() < interval->current_to()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2376
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2377
      // caller-save registers must not be included into oop-maps at calls
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2378
      assert(!is_call_site || assigned_reg >= nof_regs || !is_caller_save(assigned_reg), "interval is in a caller-save register at a call -> register will be overwritten");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2379
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2380
      VMReg name = vm_reg_for_interval(interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2381
      map->set_oop(name);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2382
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2383
      // Spill optimization: when the stack value is guaranteed to be always correct,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2384
      // then it must be added to the oop map even if the interval is currently in a register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2385
      if (interval->always_in_memory() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2386
          op->id() > interval->spill_definition_pos() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2387
          interval->assigned_reg() != interval->canonical_spill_slot()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2388
        assert(interval->spill_definition_pos() > 0, "position not set correctly");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2389
        assert(interval->canonical_spill_slot() >= LinearScan::nof_regs, "no spill slot assigned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2390
        assert(interval->assigned_reg() < LinearScan::nof_regs, "interval is on stack, so stack slot is registered twice");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2391
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2392
        map->set_oop(frame_map()->slot_regname(interval->canonical_spill_slot() - LinearScan::nof_regs));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2393
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2394
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2395
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2396
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2397
  // add oops from lock stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2398
  assert(info->stack() != NULL, "CodeEmitInfo must always have a stack");
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2399
  int locks_count = info->stack()->total_locks_size();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2400
  for (int i = 0; i < locks_count; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2401
    map->set_oop(frame_map()->monitor_object_regname(i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2402
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2403
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2404
  return map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2405
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2406
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2407
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2408
void LinearScan::compute_oop_map(IntervalWalker* iw, const LIR_OpVisitState &visitor, LIR_Op* op) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2409
  assert(visitor.info_count() > 0, "no oop map needed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2410
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2411
  // compute oop_map only for first CodeEmitInfo
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2412
  // because it is (in most cases) equal for all other infos of the same operation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2413
  CodeEmitInfo* first_info = visitor.info_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2414
  OopMap* first_oop_map = compute_oop_map(iw, op, first_info, visitor.has_call());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2415
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2416
  for (int i = 0; i < visitor.info_count(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2417
    CodeEmitInfo* info = visitor.info_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2418
    OopMap* oop_map = first_oop_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2419
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2420
    if (info->stack()->locks_size() != first_info->stack()->locks_size()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2421
      // this info has a different number of locks then the precomputed oop map
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2422
      // (possible for lock and unlock instructions) -> compute oop map with
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2423
      // correct lock information
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2424
      oop_map = compute_oop_map(iw, op, info, visitor.has_call());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2425
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2426
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2427
    if (info->_oop_map == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2428
      info->_oop_map = oop_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2429
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2430
      // a CodeEmitInfo can not be shared between different LIR-instructions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2431
      // because interval splitting can occur anywhere between two instructions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2432
      // and so the oop maps must be different
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2433
      // -> check if the already set oop_map is exactly the one calculated for this operation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2434
      assert(info->_oop_map == oop_map, "same CodeEmitInfo used for multiple LIR instructions");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2435
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2436
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2437
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2438
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2439
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2440
// frequently used constants
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2441
ConstantOopWriteValue LinearScan::_oop_null_scope_value = ConstantOopWriteValue(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2442
ConstantIntValue      LinearScan::_int_m1_scope_value = ConstantIntValue(-1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2443
ConstantIntValue      LinearScan::_int_0_scope_value =  ConstantIntValue(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2444
ConstantIntValue      LinearScan::_int_1_scope_value =  ConstantIntValue(1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2445
ConstantIntValue      LinearScan::_int_2_scope_value =  ConstantIntValue(2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2446
LocationValue         _illegal_value = LocationValue(Location());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2447
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2448
void LinearScan::init_compute_debug_info() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2449
  // cache for frequently used scope values
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2450
  // (cpu registers and stack slots)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2451
  _scope_value_cache = ScopeValueArray((LinearScan::nof_cpu_regs + frame_map()->argcount() + max_spills()) * 2, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2452
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2453
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2454
MonitorValue* LinearScan::location_for_monitor_index(int monitor_index) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2455
  Location loc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2456
  if (!frame_map()->location_for_monitor_object(monitor_index, &loc)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2457
    bailout("too large frame");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2458
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2459
  ScopeValue* object_scope_value = new LocationValue(loc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2460
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2461
  if (!frame_map()->location_for_monitor_lock(monitor_index, &loc)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2462
    bailout("too large frame");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2463
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2464
  return new MonitorValue(object_scope_value, loc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2465
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2466
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2467
LocationValue* LinearScan::location_for_name(int name, Location::Type loc_type) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2468
  Location loc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2469
  if (!frame_map()->locations_for_slot(name, loc_type, &loc)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2470
    bailout("too large frame");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2471
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2472
  return new LocationValue(loc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2473
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2474
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2475
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2476
int LinearScan::append_scope_value_for_constant(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2477
  assert(opr->is_constant(), "should not be called otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2478
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2479
  LIR_Const* c = opr->as_constant_ptr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2480
  BasicType t = c->type();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2481
  switch (t) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2482
    case T_OBJECT: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2483
      jobject value = c->as_jobject();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2484
      if (value == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2485
        scope_values->append(&_oop_null_scope_value);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2486
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2487
        scope_values->append(new ConstantOopWriteValue(c->as_jobject()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2488
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2489
      return 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2490
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2491
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2492
    case T_INT: // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2493
    case T_FLOAT: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2494
      int value = c->as_jint_bits();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2495
      switch (value) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2496
        case -1: scope_values->append(&_int_m1_scope_value); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2497
        case 0:  scope_values->append(&_int_0_scope_value); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2498
        case 1:  scope_values->append(&_int_1_scope_value); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2499
        case 2:  scope_values->append(&_int_2_scope_value); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2500
        default: scope_values->append(new ConstantIntValue(c->as_jint_bits())); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2501
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2502
      return 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2503
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2504
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2505
    case T_LONG: // fall through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2506
    case T_DOUBLE: {
4430
95b539dfa1e8 6769124: various 64-bit fixes for c1
roland
parents: 3261
diff changeset
  2507
#ifdef _LP64
95b539dfa1e8 6769124: various 64-bit fixes for c1
roland
parents: 3261
diff changeset
  2508
      scope_values->append(&_int_0_scope_value);
95b539dfa1e8 6769124: various 64-bit fixes for c1
roland
parents: 3261
diff changeset
  2509
      scope_values->append(new ConstantLongValue(c->as_jlong_bits()));
95b539dfa1e8 6769124: various 64-bit fixes for c1
roland
parents: 3261
diff changeset
  2510
#else
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2511
      if (hi_word_offset_in_bytes > lo_word_offset_in_bytes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2512
        scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2513
        scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2514
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2515
        scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2516
        scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2517
      }
4430
95b539dfa1e8 6769124: various 64-bit fixes for c1
roland
parents: 3261
diff changeset
  2518
#endif
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2519
      return 2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2520
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2521
5048
c31b6243f37e 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 4430
diff changeset
  2522
    case T_ADDRESS: {
c31b6243f37e 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 4430
diff changeset
  2523
#ifdef _LP64
c31b6243f37e 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 4430
diff changeset
  2524
      scope_values->append(new ConstantLongValue(c->as_jint()));
c31b6243f37e 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 4430
diff changeset
  2525
#else
c31b6243f37e 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 4430
diff changeset
  2526
      scope_values->append(new ConstantIntValue(c->as_jint()));
c31b6243f37e 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 4430
diff changeset
  2527
#endif
c31b6243f37e 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 4430
diff changeset
  2528
      return 1;
c31b6243f37e 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 4430
diff changeset
  2529
    }
c31b6243f37e 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 4430
diff changeset
  2530
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2531
    default:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2532
      ShouldNotReachHere();
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2533
      return -1;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2534
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2535
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2536
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2537
int LinearScan::append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2538
  if (opr->is_single_stack()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2539
    int stack_idx = opr->single_stack_ix();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2540
    bool is_oop = opr->is_oop_register();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2541
    int cache_idx = (stack_idx + LinearScan::nof_cpu_regs) * 2 + (is_oop ? 1 : 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2542
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2543
    ScopeValue* sv = _scope_value_cache.at(cache_idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2544
    if (sv == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2545
      Location::Type loc_type = is_oop ? Location::oop : Location::normal;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2546
      sv = location_for_name(stack_idx, loc_type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2547
      _scope_value_cache.at_put(cache_idx, sv);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2548
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2549
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2550
    // check if cached value is correct
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2551
    DEBUG_ONLY(assert_equal(sv, location_for_name(stack_idx, is_oop ? Location::oop : Location::normal)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2552
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2553
    scope_values->append(sv);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2554
    return 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2555
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2556
  } else if (opr->is_single_cpu()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2557
    bool is_oop = opr->is_oop_register();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2558
    int cache_idx = opr->cpu_regnr() * 2 + (is_oop ? 1 : 0);
4430
95b539dfa1e8 6769124: various 64-bit fixes for c1
roland
parents: 3261
diff changeset
  2559
    Location::Type int_loc_type = NOT_LP64(Location::normal) LP64_ONLY(Location::int_in_long);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2560
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2561
    ScopeValue* sv = _scope_value_cache.at(cache_idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2562
    if (sv == NULL) {
4430
95b539dfa1e8 6769124: various 64-bit fixes for c1
roland
parents: 3261
diff changeset
  2563
      Location::Type loc_type = is_oop ? Location::oop : int_loc_type;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2564
      VMReg rname = frame_map()->regname(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2565
      sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2566
      _scope_value_cache.at_put(cache_idx, sv);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2567
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2568
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2569
    // check if cached value is correct
4430
95b539dfa1e8 6769124: various 64-bit fixes for c1
roland
parents: 3261
diff changeset
  2570
    DEBUG_ONLY(assert_equal(sv, new LocationValue(Location::new_reg_loc(is_oop ? Location::oop : int_loc_type, frame_map()->regname(opr)))));
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2571
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2572
    scope_values->append(sv);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2573
    return 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2574
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2575
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2576
  } else if (opr->is_single_xmm()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2577
    VMReg rname = opr->as_xmm_float_reg()->as_VMReg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2578
    LocationValue* sv = new LocationValue(Location::new_reg_loc(Location::normal, rname));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2579
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2580
    scope_values->append(sv);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2581
    return 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2582
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2583
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2584
  } else if (opr->is_single_fpu()) {
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2585
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2586
    // the exact location of fpu stack values is only known
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2587
    // during fpu stack allocation, so the stack allocator object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2588
    // must be present
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2589
    assert(use_fpu_stack_allocation(), "should not have float stack values without fpu stack allocation (all floats must be SSE2)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2590
    assert(_fpu_stack_allocator != NULL, "must be present");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2591
    opr = _fpu_stack_allocator->to_fpu_stack(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2592
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2593
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2594
    Location::Type loc_type = float_saved_as_double ? Location::float_in_dbl : Location::normal;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2595
    VMReg rname = frame_map()->fpu_regname(opr->fpu_regnr());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2596
    LocationValue* sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2597
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2598
    scope_values->append(sv);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2599
    return 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2600
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2601
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2602
    // double-size operands
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2603
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2604
    ScopeValue* first;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2605
    ScopeValue* second;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2606
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2607
    if (opr->is_double_stack()) {
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2608
#ifdef _LP64
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2609
      Location loc1;
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2610
      Location::Type loc_type = opr->type() == T_LONG ? Location::lng : Location::dbl;
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2611
      if (!frame_map()->locations_for_slot(opr->double_stack_ix(), loc_type, &loc1, NULL)) {
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2612
        bailout("too large frame");
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2613
      }
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2614
      // Does this reverse on x86 vs. sparc?
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2615
      first =  new LocationValue(loc1);
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2616
      second = &_int_0_scope_value;
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2617
#else
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2618
      Location loc1, loc2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2619
      if (!frame_map()->locations_for_slot(opr->double_stack_ix(), Location::normal, &loc1, &loc2)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2620
        bailout("too large frame");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2621
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2622
      first =  new LocationValue(loc1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2623
      second = new LocationValue(loc2);
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2624
#endif // _LP64
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2625
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2626
    } else if (opr->is_double_cpu()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2627
#ifdef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2628
      VMReg rname_first = opr->as_register_lo()->as_VMReg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2629
      first = new LocationValue(Location::new_reg_loc(Location::lng, rname_first));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2630
      second = &_int_0_scope_value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2631
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2632
      VMReg rname_first = opr->as_register_lo()->as_VMReg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2633
      VMReg rname_second = opr->as_register_hi()->as_VMReg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2634
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2635
      if (hi_word_offset_in_bytes < lo_word_offset_in_bytes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2636
        // lo/hi and swapped relative to first and second, so swap them
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2637
        VMReg tmp = rname_first;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2638
        rname_first = rname_second;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2639
        rname_second = tmp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2640
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2641
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2642
      first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2643
      second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2644
#endif //_LP64
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2645
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2646
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2647
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2648
    } else if (opr->is_double_xmm()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2649
      assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2650
      VMReg rname_first  = opr->as_xmm_double_reg()->as_VMReg();
5253
d2c37eee9a65 6942223: c1 64 bit fixes
iveresov
parents: 5048
diff changeset
  2651
#  ifdef _LP64
d2c37eee9a65 6942223: c1 64 bit fixes
iveresov
parents: 5048
diff changeset
  2652
      first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first));
d2c37eee9a65 6942223: c1 64 bit fixes
iveresov
parents: 5048
diff changeset
  2653
      second = &_int_0_scope_value;
d2c37eee9a65 6942223: c1 64 bit fixes
iveresov
parents: 5048
diff changeset
  2654
#  else
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2655
      first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2656
      // %%% This is probably a waste but we'll keep things as they were for now
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2657
      if (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2658
        VMReg rname_second = rname_first->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2659
        second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2660
      }
5253
d2c37eee9a65 6942223: c1 64 bit fixes
iveresov
parents: 5048
diff changeset
  2661
#  endif
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2662
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2663
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2664
    } else if (opr->is_double_fpu()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2665
      // On SPARC, fpu_regnrLo/fpu_regnrHi represents the two halves of
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2666
      // the double as float registers in the native ordering. On X86,
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2667
      // fpu_regnrLo is a FPU stack slot whose VMReg represents
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2668
      // the low-order word of the double and fpu_regnrLo + 1 is the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2669
      // name for the other half.  *first and *second must represent the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2670
      // least and most significant words, respectively.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2671
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  2672
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2673
      // the exact location of fpu stack values is only known
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2674
      // during fpu stack allocation, so the stack allocator object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2675
      // must be present
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2676
      assert(use_fpu_stack_allocation(), "should not have float stack values without fpu stack allocation (all floats must be SSE2)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2677
      assert(_fpu_stack_allocator != NULL, "must be present");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2678
      opr = _fpu_stack_allocator->to_fpu_stack(opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2679
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2680
      assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrHi is used)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2681
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2682
#ifdef SPARC
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2683
      assert(opr->fpu_regnrLo() == opr->fpu_regnrHi() + 1, "assumed in calculation (only fpu_regnrHi is used)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2684
#endif
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2685
#ifdef ARM
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2686
      assert(opr->fpu_regnrHi() == opr->fpu_regnrLo() + 1, "assumed in calculation (only fpu_regnrLo is used)");
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2687
#endif
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2688
#ifdef PPC
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2689
      assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrHi is used)");
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  2690
#endif
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2691
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2692
      VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrHi());
5253
d2c37eee9a65 6942223: c1 64 bit fixes
iveresov
parents: 5048
diff changeset
  2693
#ifdef _LP64
d2c37eee9a65 6942223: c1 64 bit fixes
iveresov
parents: 5048
diff changeset
  2694
      first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first));
d2c37eee9a65 6942223: c1 64 bit fixes
iveresov
parents: 5048
diff changeset
  2695
      second = &_int_0_scope_value;
d2c37eee9a65 6942223: c1 64 bit fixes
iveresov
parents: 5048
diff changeset
  2696
#else
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2697
      first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2698
      // %%% This is probably a waste but we'll keep things as they were for now
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2699
      if (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2700
        VMReg rname_second = rname_first->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2701
        second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2702
      }
5253
d2c37eee9a65 6942223: c1 64 bit fixes
iveresov
parents: 5048
diff changeset
  2703
#endif
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2704
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2705
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2706
      ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2707
      first = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2708
      second = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2709
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2710
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2711
    assert(first != NULL && second != NULL, "must be set");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2712
    // The convention the interpreter uses is that the second local
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2713
    // holds the first raw word of the native double representation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2714
    // This is actually reasonable, since locals and stack arrays
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2715
    // grow downwards in all implementations.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2716
    // (If, on some machine, the interpreter's Java locals or stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2717
    // were to grow upwards, the embedded doubles would be word-swapped.)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2718
    scope_values->append(second);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2719
    scope_values->append(first);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2720
    return 2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2721
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2722
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2723
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2724
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2725
int LinearScan::append_scope_value(int op_id, Value value, GrowableArray<ScopeValue*>* scope_values) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2726
  if (value != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2727
    LIR_Opr opr = value->operand();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2728
    Constant* con = value->as_Constant();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2729
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2730
    assert(con == NULL || opr->is_virtual() || opr->is_constant() || opr->is_illegal(), "asumption: Constant instructions have only constant operands (or illegal if constant is optimized away)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2731
    assert(con != NULL || opr->is_virtual(), "asumption: non-Constant instructions have only virtual operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2732
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2733
    if (con != NULL && !con->is_pinned() && !opr->is_constant()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2734
      // Unpinned constants may have a virtual operand for a part of the lifetime
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2735
      // or may be illegal when it was optimized away,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2736
      // so always use a constant operand
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2737
      opr = LIR_OprFact::value_type(con->type());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2738
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2739
    assert(opr->is_virtual() || opr->is_constant(), "other cases not allowed here");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2740
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2741
    if (opr->is_virtual()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2742
      LIR_OpVisitState::OprMode mode = LIR_OpVisitState::inputMode;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2743
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2744
      BlockBegin* block = block_of_op_with_id(op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2745
      if (block->number_of_sux() == 1 && op_id == block->last_lir_instruction_id()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2746
        // generating debug information for the last instruction of a block.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2747
        // if this instruction is a branch, spill moves are inserted before this branch
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2748
        // and so the wrong operand would be returned (spill moves at block boundaries are not
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2749
        // considered in the live ranges of intervals)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2750
        // Solution: use the first op_id of the branch target block instead.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2751
        if (block->lir()->instructions_list()->last()->as_OpBranch() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2752
          if (block->live_out().at(opr->vreg_number())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2753
            op_id = block->sux_at(0)->first_lir_instruction_id();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2754
            mode = LIR_OpVisitState::outputMode;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2755
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2756
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2757
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2758
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2759
      // Get current location of operand
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2760
      // The operand must be live because debug information is considered when building the intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2761
      // if the interval is not live, color_lir_opr will cause an assertion failure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2762
      opr = color_lir_opr(opr, op_id, mode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2763
      assert(!has_call(op_id) || opr->is_stack() || !is_caller_save(reg_num(opr)), "can not have caller-save register operands at calls");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2764
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2765
      // Append to ScopeValue array
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2766
      return append_scope_value_for_operand(opr, scope_values);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2767
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2768
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2769
      assert(value->as_Constant() != NULL, "all other instructions have only virtual operands");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2770
      assert(opr->is_constant(), "operand must be constant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2771
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2772
      return append_scope_value_for_constant(opr, scope_values);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2773
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2774
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2775
    // append a dummy value because real value not needed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2776
    scope_values->append(&_illegal_value);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2777
    return 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2778
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2779
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2780
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2781
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2782
IRScopeDebugInfo* LinearScan::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
  2783
  IRScopeDebugInfo* caller_debug_info = NULL;
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2784
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2785
  ValueStack* caller_state = cur_state->caller_state();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2786
  if (caller_state != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2787
    // process recursively to compute outermost scope first
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2788
    caller_debug_info = compute_debug_info_for_scope(op_id, cur_scope->caller(), caller_state, innermost_state);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2789
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2790
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2791
  // initialize these to null.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2792
  // If we don't need deopt info or there are no locals, expressions or monitors,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2793
  // then these get recorded as no information and avoids the allocation of 0 length arrays.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2794
  GrowableArray<ScopeValue*>*   locals      = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2795
  GrowableArray<ScopeValue*>*   expressions = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2796
  GrowableArray<MonitorValue*>* monitors    = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2797
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2798
  // describe local variable values
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2799
  int nof_locals = cur_state->locals_size();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2800
  if (nof_locals > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2801
    locals = new GrowableArray<ScopeValue*>(nof_locals);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2802
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2803
    int pos = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2804
    while (pos < nof_locals) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2805
      assert(pos < cur_state->locals_size(), "why not?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2806
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2807
      Value local = cur_state->local_at(pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2808
      pos += append_scope_value(op_id, local, locals);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2809
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2810
      assert(locals->length() == pos, "must match");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2811
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2812
    assert(locals->length() == cur_scope->method()->max_locals(), "wrong number of locals");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2813
    assert(locals->length() == cur_state->locals_size(), "wrong number of locals");
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2814
  } else if (cur_scope->method()->max_locals() > 0) {
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2815
    assert(cur_state->kind() == ValueStack::EmptyExceptionState, "should be");
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2816
    nof_locals = cur_scope->method()->max_locals();
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2817
    locals = new GrowableArray<ScopeValue*>(nof_locals);
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2818
    for(int i = 0; i < nof_locals; i++) {
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2819
      locals->append(&_illegal_value);
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2820
    }
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2821
  }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2822
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2823
  // describe expression stack
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2824
  int nof_stack = cur_state->stack_size();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2825
  if (nof_stack > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2826
    expressions = new GrowableArray<ScopeValue*>(nof_stack);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2827
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2828
    int pos = 0;
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2829
    while (pos < nof_stack) {
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2830
      Value expression = cur_state->stack_at_inc(pos);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2831
      append_scope_value(op_id, expression, expressions);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2832
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2833
      assert(expressions->length() == pos, "must match");
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2834
    }
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2835
    assert(expressions->length() == cur_state->stack_size(), "wrong number of stack entries");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2836
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2837
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2838
  // describe monitors
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2839
  int nof_locks = cur_state->locks_size();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2840
  if (nof_locks > 0) {
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2841
    int lock_offset = cur_state->caller_state() != NULL ? cur_state->caller_state()->total_locks_size() : 0;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2842
    monitors = new GrowableArray<MonitorValue*>(nof_locks);
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2843
    for (int i = 0; i < nof_locks; i++) {
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2844
      monitors->append(location_for_monitor_index(lock_offset + i));
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2845
    }
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2846
  }
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2847
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2848
  return new IRScopeDebugInfo(cur_scope, cur_state->bci(), locals, expressions, monitors, caller_debug_info);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2849
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2850
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2851
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2852
void LinearScan::compute_debug_info(CodeEmitInfo* info, int op_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2853
  TRACE_LINEAR_SCAN(3, tty->print_cr("creating debug information at op_id %d", op_id));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2854
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2855
  IRScope* innermost_scope = info->scope();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2856
  ValueStack* innermost_state = info->stack();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2857
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2858
  assert(innermost_scope != NULL && innermost_state != NULL, "why is it missing?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2859
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2860
  DEBUG_ONLY(check_stack_depth(info, innermost_state->stack_size()));
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2861
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2862
  if (info->_scope_debug_info == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2863
    // compute debug information
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2864
    info->_scope_debug_info = compute_debug_info_for_scope(op_id, innermost_scope, innermost_state, innermost_state);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2865
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2866
    // debug information already set. Check that it is correct from the current point of view
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6742
diff changeset
  2867
    DEBUG_ONLY(assert_equal(info->_scope_debug_info, compute_debug_info_for_scope(op_id, innermost_scope, innermost_state, innermost_state)));
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2868
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2869
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2870
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2871
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2872
void LinearScan::assign_reg_num(LIR_OpList* instructions, IntervalWalker* iw) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2873
  LIR_OpVisitState visitor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2874
  int num_inst = instructions->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2875
  bool has_dead = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2876
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2877
  for (int j = 0; j < num_inst; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2878
    LIR_Op* op = instructions->at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2879
    if (op == NULL) {  // this can happen when spill-moves are removed in eliminate_spill_moves
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2880
      has_dead = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2881
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2882
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2883
    int op_id = op->id();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2884
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2885
    // visit instruction to get list of operands
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2886
    visitor.visit(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2887
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2888
    // iterate all modes of the visitor and process all virtual operands
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2889
    for_each_visitor_mode(mode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2890
      int n = visitor.opr_count(mode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2891
      for (int k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2892
        LIR_Opr opr = visitor.opr_at(mode, k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2893
        if (opr->is_virtual_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2894
          visitor.set_opr_at(mode, k, color_lir_opr(opr, op_id, mode));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2895
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2896
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2897
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2898
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2899
    if (visitor.info_count() > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2900
      // exception handling
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2901
      if (compilation()->has_exception_handlers()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2902
        XHandlers* xhandlers = visitor.all_xhandler();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2903
        int n = xhandlers->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2904
        for (int k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2905
          XHandler* handler = xhandlers->handler_at(k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2906
          if (handler->entry_code() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2907
            assign_reg_num(handler->entry_code()->instructions_list(), NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2908
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2909
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2910
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2911
        assert(visitor.all_xhandler()->length() == 0, "missed exception handler");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2912
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2913
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2914
      // compute oop map
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2915
      assert(iw != NULL, "needed for compute_oop_map");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2916
      compute_oop_map(iw, visitor, op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2917
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2918
      // compute debug information
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2919
      if (!use_fpu_stack_allocation()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2920
        // compute debug information if fpu stack allocation is not needed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2921
        // when fpu stack allocation is needed, the debug information can not
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2922
        // be computed here because the exact location of fpu operands is not known
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2923
        // -> debug information is created inside the fpu stack allocator
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2924
        int n = visitor.info_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2925
        for (int k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2926
          compute_debug_info(visitor.info_at(k), op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2927
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2928
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2929
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2930
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2931
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2932
    // make sure we haven't made the op invalid.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2933
    op->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2934
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2935
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2936
    // remove useless moves
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2937
    if (op->code() == lir_move) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2938
      assert(op->as_Op1() != NULL, "move must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2939
      LIR_Op1* move = (LIR_Op1*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2940
      LIR_Opr src = move->in_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2941
      LIR_Opr dst = move->result_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2942
      if (dst == src ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2943
          !dst->is_pointer() && !src->is_pointer() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2944
          src->is_same_register(dst)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2945
        instructions->at_put(j, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2946
        has_dead = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2947
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2948
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2949
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2950
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2951
  if (has_dead) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2952
    // iterate all instructions of the block and remove all null-values.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2953
    int insert_point = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2954
    for (int j = 0; j < num_inst; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2955
      LIR_Op* op = instructions->at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2956
      if (op != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2957
        if (insert_point != j) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2958
          instructions->at_put(insert_point, op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2959
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2960
        insert_point++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2961
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2962
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2963
    instructions->truncate(insert_point);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2964
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2965
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2966
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2967
void LinearScan::assign_reg_num() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2968
  TIME_LINEAR_SCAN(timer_assign_reg_num);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2969
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2970
  init_compute_debug_info();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2971
  IntervalWalker* iw = init_compute_oop_maps();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2972
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2973
  int num_blocks = block_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2974
  for (int i = 0; i < num_blocks; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2975
    BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2976
    assign_reg_num(block->lir()->instructions_list(), iw);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2977
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2978
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2979
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2980
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2981
void LinearScan::do_linear_scan() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2982
  NOT_PRODUCT(_total_timer.begin_method());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2983
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2984
  number_instructions();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2985
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2986
  NOT_PRODUCT(print_lir(1, "Before Register Allocation"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2987
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2988
  compute_local_live_sets();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2989
  compute_global_live_sets();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2990
  CHECK_BAILOUT();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2991
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2992
  build_intervals();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2993
  CHECK_BAILOUT();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2994
  sort_intervals_before_allocation();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2995
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2996
  NOT_PRODUCT(print_intervals("Before Register Allocation"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2997
  NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_before_alloc));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2998
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2999
  allocate_registers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3000
  CHECK_BAILOUT();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3001
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3002
  resolve_data_flow();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3003
  if (compilation()->has_exception_handlers()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3004
    resolve_exception_handlers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3005
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3006
  // fill in number of spill slots into frame_map
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3007
  propagate_spill_slots();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3008
  CHECK_BAILOUT();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3009
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3010
  NOT_PRODUCT(print_intervals("After Register Allocation"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3011
  NOT_PRODUCT(print_lir(2, "LIR after register allocation:"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3012
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3013
  sort_intervals_after_allocation();
2566
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3014
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3015
  DEBUG_ONLY(verify());
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3016
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3017
  eliminate_spill_moves();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3018
  assign_reg_num();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3019
  CHECK_BAILOUT();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3020
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3021
  NOT_PRODUCT(print_lir(2, "LIR after assignment of register numbers:"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3022
  NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_after_asign));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3023
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3024
  { TIME_LINEAR_SCAN(timer_allocate_fpu_stack);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3025
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3026
    if (use_fpu_stack_allocation()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3027
      allocate_fpu_stack(); // Only has effect on Intel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3028
      NOT_PRODUCT(print_lir(2, "LIR after FPU stack allocation:"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3029
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3030
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3031
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3032
  { TIME_LINEAR_SCAN(timer_optimize_lir);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3033
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3034
    EdgeMoveOptimizer::optimize(ir()->code());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3035
    ControlFlowOptimizer::optimize(ir()->code());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3036
    // check that cfg is still correct after optimizations
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3037
    ir()->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3038
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3039
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3040
  NOT_PRODUCT(print_lir(1, "Before Code Generation", false));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3041
  NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_final));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3042
  NOT_PRODUCT(_total_timer.end_method(this));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3043
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3044
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3045
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3046
// ********** Printing functions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3047
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3048
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3049
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3050
void LinearScan::print_timers(double total) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3051
  _total_timer.print(total);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3052
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3053
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3054
void LinearScan::print_statistics() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3055
  _stat_before_alloc.print("before allocation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3056
  _stat_after_asign.print("after assignment of register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3057
  _stat_final.print("after optimization");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3058
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3059
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3060
void LinearScan::print_bitmap(BitMap& b) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3061
  for (unsigned int i = 0; i < b.size(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3062
    if (b.at(i)) tty->print("%d ", i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3063
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3064
  tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3065
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3066
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3067
void LinearScan::print_intervals(const char* label) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3068
  if (TraceLinearScanLevel >= 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3069
    int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3070
    tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3071
    tty->print_cr("%s", label);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3072
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3073
    for (i = 0; i < interval_count(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3074
      Interval* interval = interval_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3075
      if (interval != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3076
        interval->print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3077
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3078
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3079
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3080
    tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3081
    tty->print_cr("--- Basic Blocks ---");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3082
    for (i = 0; i < block_count(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3083
      BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3084
      tty->print("B%d [%d, %d, %d, %d] ", block->block_id(), block->first_lir_instruction_id(), block->last_lir_instruction_id(), block->loop_index(), block->loop_depth());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3085
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3086
    tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3087
    tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3088
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3089
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3090
  if (PrintCFGToFile) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3091
    CFGPrinter::print_intervals(&_intervals, label);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3092
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3093
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3094
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3095
void LinearScan::print_lir(int level, const char* label, bool hir_valid) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3096
  if (TraceLinearScanLevel >= level) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3097
    tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3098
    tty->print_cr("%s", label);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3099
    print_LIR(ir()->linear_scan_order());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3100
    tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3101
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3102
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3103
  if (level == 1 && PrintCFGToFile) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3104
    CFGPrinter::print_cfg(ir()->linear_scan_order(), label, hir_valid, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3105
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3106
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3107
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3108
#endif //PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3109
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3110
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3111
// ********** verification functions for allocation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3112
// (check that all intervals have a correct register and that no registers are overwritten)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3113
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3114
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3115
void LinearScan::verify() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3116
  TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying intervals ******************************************"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3117
  verify_intervals();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3118
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3119
  TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying that no oops are in fixed intervals ****************"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3120
  verify_no_oops_in_fixed_intervals();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3121
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3122
  TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying that unpinned constants are not alive across block boundaries"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3123
  verify_constants();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3124
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3125
  TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying register allocation ********************************"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3126
  verify_registers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3127
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3128
  TRACE_LINEAR_SCAN(2, tty->print_cr("********* no errors found **********************************************"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3129
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3130
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3131
void LinearScan::verify_intervals() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3132
  int len = interval_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3133
  bool has_error = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3134
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3135
  for (int i = 0; i < len; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3136
    Interval* i1 = interval_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3137
    if (i1 == NULL) continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3138
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3139
    i1->check_split_children();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3140
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3141
    if (i1->reg_num() != i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3142
      tty->print_cr("Interval %d is on position %d in list", i1->reg_num(), i); i1->print(); tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3143
      has_error = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3144
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3145
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3146
    if (i1->reg_num() >= LIR_OprDesc::vreg_base && i1->type() == T_ILLEGAL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3147
      tty->print_cr("Interval %d has no type assigned", i1->reg_num()); i1->print(); tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3148
      has_error = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3149
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3150
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3151
    if (i1->assigned_reg() == any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3152
      tty->print_cr("Interval %d has no register assigned", i1->reg_num()); i1->print(); tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3153
      has_error = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3154
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3155
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3156
    if (i1->assigned_reg() == i1->assigned_regHi()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3157
      tty->print_cr("Interval %d: low and high register equal", i1->reg_num()); i1->print(); tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3158
      has_error = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3159
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3160
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3161
    if (!is_processed_reg_num(i1->assigned_reg())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3162
      tty->print_cr("Can not have an Interval for an ignored register"); i1->print(); tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3163
      has_error = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3164
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3165
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3166
    if (i1->first() == Range::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3167
      tty->print_cr("Interval %d has no Range", i1->reg_num()); i1->print(); tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3168
      has_error = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3169
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3170
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3171
    for (Range* r = i1->first(); r != Range::end(); r = r->next()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3172
      if (r->from() >= r->to()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3173
        tty->print_cr("Interval %d has zero length range", i1->reg_num()); i1->print(); tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3174
        has_error = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3175
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3176
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3177
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3178
    for (int j = i + 1; j < len; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3179
      Interval* i2 = interval_at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3180
      if (i2 == NULL) continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3181
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3182
      // special intervals that are created in MoveResolver
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3183
      // -> ignore them because the range information has no meaning there
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3184
      if (i1->from() == 1 && i1->to() == 2) continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3185
      if (i2->from() == 1 && i2->to() == 2) continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3186
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3187
      int r1 = i1->assigned_reg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3188
      int r1Hi = i1->assigned_regHi();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3189
      int r2 = i2->assigned_reg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3190
      int r2Hi = i2->assigned_regHi();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3191
      if (i1->intersects(i2) && (r1 == r2 || r1 == r2Hi || (r1Hi != any_reg && (r1Hi == r2 || r1Hi == r2Hi)))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3192
        tty->print_cr("Intervals %d and %d overlap and have the same register assigned", i1->reg_num(), i2->reg_num());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3193
        i1->print(); tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3194
        i2->print(); tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3195
        has_error = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3196
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3197
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3198
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3199
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3200
  assert(has_error == false, "register allocation invalid");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3201
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3202
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3203
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3204
void LinearScan::verify_no_oops_in_fixed_intervals() {
2566
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3205
  Interval* fixed_intervals;
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3206
  Interval* other_intervals;
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3207
  create_unhandled_lists(&fixed_intervals, &other_intervals, is_precolored_cpu_interval, NULL);
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3208
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3209
  // to ensure a walking until the last instruction id, add a dummy interval
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3210
  // with a high operation id
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3211
  other_intervals = new Interval(any_reg);
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3212
  other_intervals->add_range(max_jint - 2, max_jint - 1);
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3213
  IntervalWalker* iw = new IntervalWalker(this, fixed_intervals, other_intervals);
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3214
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3215
  LIR_OpVisitState visitor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3216
  for (int i = 0; i < block_count(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3217
    BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3218
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3219
    LIR_OpList* instructions = block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3220
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3221
    for (int j = 0; j < instructions->length(); j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3222
      LIR_Op* op = instructions->at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3223
      int op_id = op->id();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3224
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3225
      visitor.visit(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3226
2566
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3227
      if (visitor.info_count() > 0) {
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3228
        iw->walk_before(op->id());
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3229
        bool check_live = true;
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3230
        if (op->code() == lir_move) {
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3231
          LIR_Op1* move = (LIR_Op1*)op;
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3232
          check_live = (move->patch_code() == lir_patch_none);
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3233
        }
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3234
        LIR_OpBranch* branch = op->as_OpBranch();
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3235
        if (branch != NULL && branch->stub() != NULL && branch->stub()->is_exception_throw_stub()) {
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3236
          // Don't bother checking the stub in this case since the
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3237
          // exception stub will never return to normal control flow.
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3238
          check_live = false;
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3239
        }
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3240
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3241
        // Make sure none of the fixed registers is live across an
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3242
        // oopmap since we can't handle that correctly.
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3243
        if (check_live) {
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3244
          for (Interval* interval = iw->active_first(fixedKind);
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3245
               interval != Interval::end();
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3246
               interval = interval->next()) {
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3247
            if (interval->current_to() > op->id() + 1) {
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3248
              // This interval is live out of this op so make sure
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3249
              // that this interval represents some value that's
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3250
              // referenced by this op either as an input or output.
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3251
              bool ok = false;
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3252
              for_each_visitor_mode(mode) {
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3253
                int n = visitor.opr_count(mode);
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3254
                for (int k = 0; k < n; k++) {
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3255
                  LIR_Opr opr = visitor.opr_at(mode, k);
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3256
                  if (opr->is_fixed_cpu()) {
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3257
                    if (interval_at(reg_num(opr)) == interval) {
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3258
                      ok = true;
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3259
                      break;
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3260
                    }
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3261
                    int hi = reg_numHi(opr);
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3262
                    if (hi != -1 && interval_at(hi) == interval) {
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3263
                      ok = true;
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3264
                      break;
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3265
                    }
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3266
                  }
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3267
                }
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3268
              }
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3269
              assert(ok, "fixed intervals should never be live across an oopmap point");
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3270
            }
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3271
          }
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3272
        }
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3273
      }
865943584ecc 6828024: verification of fixed interval usage is too weak
never
parents: 1217
diff changeset
  3274
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3275
      // oop-maps at calls do not contain registers, so check is not needed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3276
      if (!visitor.has_call()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3277
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3278
        for_each_visitor_mode(mode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3279
          int n = visitor.opr_count(mode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3280
          for (int k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3281
            LIR_Opr opr = visitor.opr_at(mode, k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3282
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3283
            if (opr->is_fixed_cpu() && opr->is_oop()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3284
              // operand is a non-virtual cpu register and contains an oop
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3285
              TRACE_LINEAR_SCAN(4, op->print_on(tty); tty->print("checking operand "); opr->print(); tty->cr());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3286
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3287
              Interval* interval = interval_at(reg_num(opr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3288
              assert(interval != NULL, "no interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3289
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3290
              if (mode == LIR_OpVisitState::inputMode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3291
                if (interval->to() >= op_id + 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3292
                  assert(interval->to() < op_id + 2 ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3293
                         interval->has_hole_between(op_id, op_id + 2),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3294
                         "oop input operand live after instruction");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3295
                }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3296
              } else if (mode == LIR_OpVisitState::outputMode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3297
                if (interval->from() <= op_id - 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3298
                  assert(interval->has_hole_between(op_id - 1, op_id),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3299
                         "oop input operand live after instruction");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3300
                }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3301
              }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3302
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3303
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3304
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3305
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3306
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3307
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3308
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3309
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3310
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3311
void LinearScan::verify_constants() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3312
  int num_regs = num_virtual_regs();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3313
  int size = live_set_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3314
  int num_blocks = block_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3315
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3316
  for (int i = 0; i < num_blocks; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3317
    BlockBegin* block = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3318
    BitMap live_at_edge = block->live_in();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3319
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3320
    // visit all registers where the live_at_edge bit is set
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  3321
    for (int r = (int)live_at_edge.get_next_one_offset(0, size); r < size; r = (int)live_at_edge.get_next_one_offset(r + 1, size)) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3322
      TRACE_LINEAR_SCAN(4, tty->print("checking interval %d of block B%d", r, block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3323
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3324
      Value value = gen()->instruction_for_vreg(r);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3325
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3326
      assert(value != NULL, "all intervals live across block boundaries must have Value");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3327
      assert(value->operand()->is_register() && value->operand()->is_virtual(), "value must have virtual operand");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3328
      assert(value->operand()->vreg_number() == r, "register number must match");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3329
      // TKR assert(value->as_Constant() == NULL || value->is_pinned(), "only pinned constants can be alive accross block boundaries");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3330
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3331
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3332
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3333
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3334
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3335
class RegisterVerifier: public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3336
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3337
  LinearScan*   _allocator;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3338
  BlockList     _work_list;      // all blocks that must be processed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3339
  IntervalsList _saved_states;   // saved information of previous check
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3340
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3341
  // simplified access to methods of LinearScan
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3342
  Compilation*  compilation() const              { return _allocator->compilation(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3343
  Interval*     interval_at(int reg_num) const   { return _allocator->interval_at(reg_num); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3344
  int           reg_num(LIR_Opr opr) const       { return _allocator->reg_num(opr); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3345
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3346
  // currently, only registers are processed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3347
  int           state_size()                     { return LinearScan::nof_regs; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3348
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3349
  // accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3350
  IntervalList* state_for_block(BlockBegin* block) { return _saved_states.at(block->block_id()); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3351
  void          set_state_for_block(BlockBegin* block, IntervalList* saved_state) { _saved_states.at_put(block->block_id(), saved_state); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3352
  void          add_to_work_list(BlockBegin* block) { if (!_work_list.contains(block)) _work_list.append(block); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3353
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3354
  // helper functions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3355
  IntervalList* copy(IntervalList* input_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3356
  void          state_put(IntervalList* input_state, int reg, Interval* interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3357
  bool          check_state(IntervalList* input_state, int reg, Interval* interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3358
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3359
  void process_block(BlockBegin* block);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3360
  void process_xhandler(XHandler* xhandler, IntervalList* input_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3361
  void process_successor(BlockBegin* block, IntervalList* input_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3362
  void process_operations(LIR_List* ops, IntervalList* input_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3363
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3364
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3365
  RegisterVerifier(LinearScan* allocator)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3366
    : _allocator(allocator)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3367
    , _work_list(16)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3368
    , _saved_states(BlockBegin::number_of_blocks(), NULL)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3369
  { }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3370
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3371
  void verify(BlockBegin* start);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3372
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3373
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3374
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3375
// entry function from LinearScan that starts the verification
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3376
void LinearScan::verify_registers() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3377
  RegisterVerifier verifier(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3378
  verifier.verify(block_at(0));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3379
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3380
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3381
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3382
void RegisterVerifier::verify(BlockBegin* start) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3383
  // setup input registers (method arguments) for first block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3384
  IntervalList* input_state = new IntervalList(state_size(), NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3385
  CallingConvention* args = compilation()->frame_map()->incoming_arguments();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3386
  for (int n = 0; n < args->length(); n++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3387
    LIR_Opr opr = args->at(n);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3388
    if (opr->is_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3389
      Interval* interval = interval_at(reg_num(opr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3390
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3391
      if (interval->assigned_reg() < state_size()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3392
        input_state->at_put(interval->assigned_reg(), interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3393
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3394
      if (interval->assigned_regHi() != LinearScan::any_reg && interval->assigned_regHi() < state_size()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3395
        input_state->at_put(interval->assigned_regHi(), interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3396
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3397
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3398
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3399
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3400
  set_state_for_block(start, input_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3401
  add_to_work_list(start);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3402
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3403
  // main loop for verification
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3404
  do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3405
    BlockBegin* block = _work_list.at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3406
    _work_list.remove_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3407
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3408
    process_block(block);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3409
  } while (!_work_list.is_empty());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3410
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3411
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3412
void RegisterVerifier::process_block(BlockBegin* block) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3413
  TRACE_LINEAR_SCAN(2, tty->cr(); tty->print_cr("process_block B%d", block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3414
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3415
  // must copy state because it is modified
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3416
  IntervalList* input_state = copy(state_for_block(block));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3417
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3418
  if (TraceLinearScanLevel >= 4) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3419
    tty->print_cr("Input-State of intervals:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3420
    tty->print("    ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3421
    for (int i = 0; i < state_size(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3422
      if (input_state->at(i) != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3423
        tty->print(" %4d", input_state->at(i)->reg_num());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3424
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3425
        tty->print("   __");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3426
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3427
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3428
    tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3429
    tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3430
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3431
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3432
  // process all operations of the block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3433
  process_operations(block->lir(), input_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3434
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3435
  // iterate all successors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3436
  for (int i = 0; i < block->number_of_sux(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3437
    process_successor(block->sux_at(i), input_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3438
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3439
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3440
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3441
void RegisterVerifier::process_xhandler(XHandler* xhandler, IntervalList* input_state) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3442
  TRACE_LINEAR_SCAN(2, tty->print_cr("process_xhandler B%d", xhandler->entry_block()->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3443
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3444
  // must copy state because it is modified
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3445
  input_state = copy(input_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3446
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3447
  if (xhandler->entry_code() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3448
    process_operations(xhandler->entry_code(), input_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3449
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3450
  process_successor(xhandler->entry_block(), input_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3451
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3452
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3453
void RegisterVerifier::process_successor(BlockBegin* block, IntervalList* input_state) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3454
  IntervalList* saved_state = state_for_block(block);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3455
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3456
  if (saved_state != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3457
    // this block was already processed before.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3458
    // check if new input_state is consistent with saved_state
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3459
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3460
    bool saved_state_correct = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3461
    for (int i = 0; i < state_size(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3462
      if (input_state->at(i) != saved_state->at(i)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3463
        // current input_state and previous saved_state assume a different
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3464
        // interval in this register -> assume that this register is invalid
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3465
        if (saved_state->at(i) != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3466
          // invalidate old calculation only if it assumed that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3467
          // register was valid. when the register was already invalid,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3468
          // then the old calculation was correct.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3469
          saved_state_correct = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3470
          saved_state->at_put(i, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3471
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3472
          TRACE_LINEAR_SCAN(4, tty->print_cr("process_successor B%d: invalidating slot %d", block->block_id(), i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3473
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3474
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3475
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3476
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3477
    if (saved_state_correct) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3478
      // already processed block with correct input_state
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3479
      TRACE_LINEAR_SCAN(2, tty->print_cr("process_successor B%d: previous visit already correct", block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3480
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3481
      // must re-visit this block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3482
      TRACE_LINEAR_SCAN(2, tty->print_cr("process_successor B%d: must re-visit because input state changed", block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3483
      add_to_work_list(block);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3484
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3485
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3486
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3487
    // block was not processed before, so set initial input_state
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3488
    TRACE_LINEAR_SCAN(2, tty->print_cr("process_successor B%d: initial visit", block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3489
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3490
    set_state_for_block(block, copy(input_state));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3491
    add_to_work_list(block);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3492
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3493
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3494
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3495
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3496
IntervalList* RegisterVerifier::copy(IntervalList* input_state) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3497
  IntervalList* copy_state = new IntervalList(input_state->length());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3498
  copy_state->push_all(input_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3499
  return copy_state;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3500
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3501
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3502
void RegisterVerifier::state_put(IntervalList* input_state, int reg, Interval* interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3503
  if (reg != LinearScan::any_reg && reg < state_size()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3504
    if (interval != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3505
      TRACE_LINEAR_SCAN(4, tty->print_cr("        reg[%d] = %d", reg, interval->reg_num()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3506
    } else if (input_state->at(reg) != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3507
      TRACE_LINEAR_SCAN(4, tty->print_cr("        reg[%d] = NULL", reg));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3508
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3509
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3510
    input_state->at_put(reg, interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3511
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3512
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3513
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3514
bool RegisterVerifier::check_state(IntervalList* input_state, int reg, Interval* interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3515
  if (reg != LinearScan::any_reg && reg < state_size()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3516
    if (input_state->at(reg) != interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3517
      tty->print_cr("!! Error in register allocation: register %d does not contain interval %d", reg, interval->reg_num());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3518
      return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3519
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3520
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3521
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3522
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3523
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3524
void RegisterVerifier::process_operations(LIR_List* ops, IntervalList* input_state) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3525
  // visit all instructions of the block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3526
  LIR_OpVisitState visitor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3527
  bool has_error = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3528
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3529
  for (int i = 0; i < ops->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3530
    LIR_Op* op = ops->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3531
    visitor.visit(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3532
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3533
    TRACE_LINEAR_SCAN(4, op->print_on(tty));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3534
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3535
    // check if input operands are correct
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3536
    int j;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3537
    int n = visitor.opr_count(LIR_OpVisitState::inputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3538
    for (j = 0; j < n; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3539
      LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3540
      if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3541
        Interval* interval = interval_at(reg_num(opr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3542
        if (op->id() != -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3543
          interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::inputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3544
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3545
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3546
        has_error |= check_state(input_state, interval->assigned_reg(),   interval->split_parent());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3547
        has_error |= check_state(input_state, interval->assigned_regHi(), interval->split_parent());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3548
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3549
        // When an operand is marked with is_last_use, then the fpu stack allocator
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3550
        // removes the register from the fpu stack -> the register contains no value
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3551
        if (opr->is_last_use()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3552
          state_put(input_state, interval->assigned_reg(),   NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3553
          state_put(input_state, interval->assigned_regHi(), NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3554
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3555
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3556
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3557
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3558
    // invalidate all caller save registers at calls
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3559
    if (visitor.has_call()) {
7427
d7b79a367474 6985015: C1 needs to support compressed oops
iveresov
parents: 7397
diff changeset
  3560
      for (j = 0; j < FrameMap::nof_caller_save_cpu_regs(); j++) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3561
        state_put(input_state, reg_num(FrameMap::caller_save_cpu_reg_at(j)), NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3562
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3563
      for (j = 0; j < FrameMap::nof_caller_save_fpu_regs; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3564
        state_put(input_state, reg_num(FrameMap::caller_save_fpu_reg_at(j)), NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3565
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3566
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  3567
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3568
      for (j = 0; j < FrameMap::nof_caller_save_xmm_regs; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3569
        state_put(input_state, reg_num(FrameMap::caller_save_xmm_reg_at(j)), NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3570
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3571
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3572
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3573
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3574
    // process xhandler before output and temp operands
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3575
    XHandlers* xhandlers = visitor.all_xhandler();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3576
    n = xhandlers->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3577
    for (int k = 0; k < n; k++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3578
      process_xhandler(xhandlers->handler_at(k), input_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3579
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3580
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3581
    // set temp operands (some operations use temp operands also as output operands, so can't set them NULL)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3582
    n = visitor.opr_count(LIR_OpVisitState::tempMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3583
    for (j = 0; j < n; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3584
      LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3585
      if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3586
        Interval* interval = interval_at(reg_num(opr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3587
        if (op->id() != -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3588
          interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::tempMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3589
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3590
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3591
        state_put(input_state, interval->assigned_reg(),   interval->split_parent());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3592
        state_put(input_state, interval->assigned_regHi(), interval->split_parent());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3593
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3594
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3595
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3596
    // set output operands
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3597
    n = visitor.opr_count(LIR_OpVisitState::outputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3598
    for (j = 0; j < n; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3599
      LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3600
      if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3601
        Interval* interval = interval_at(reg_num(opr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3602
        if (op->id() != -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3603
          interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::outputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3604
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3605
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3606
        state_put(input_state, interval->assigned_reg(),   interval->split_parent());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3607
        state_put(input_state, interval->assigned_regHi(), interval->split_parent());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3608
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3609
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3610
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3611
  assert(has_error == false, "Error in register allocation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3612
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3613
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3614
#endif // ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3615
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3616
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3617
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3618
// **** Implementation of MoveResolver ******************************
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3619
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3620
MoveResolver::MoveResolver(LinearScan* allocator) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3621
  _allocator(allocator),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3622
  _multiple_reads_allowed(false),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3623
  _mapping_from(8),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3624
  _mapping_from_opr(8),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3625
  _mapping_to(8),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3626
  _insert_list(NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3627
  _insert_idx(-1),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3628
  _insertion_buffer()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3629
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3630
  for (int i = 0; i < LinearScan::nof_regs; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3631
    _register_blocked[i] = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3632
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3633
  DEBUG_ONLY(check_empty());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3634
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3635
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3636
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3637
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3638
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3639
void MoveResolver::check_empty() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3640
  assert(_mapping_from.length() == 0 && _mapping_from_opr.length() == 0 && _mapping_to.length() == 0, "list must be empty before and after processing");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3641
  for (int i = 0; i < LinearScan::nof_regs; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3642
    assert(register_blocked(i) == 0, "register map must be empty before and after processing");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3643
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3644
  assert(_multiple_reads_allowed == false, "must have default value");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3645
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3646
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3647
void MoveResolver::verify_before_resolve() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3648
  assert(_mapping_from.length() == _mapping_from_opr.length(), "length must be equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3649
  assert(_mapping_from.length() == _mapping_to.length(), "length must be equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3650
  assert(_insert_list != NULL && _insert_idx != -1, "insert position not set");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3651
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3652
  int i, j;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3653
  if (!_multiple_reads_allowed) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3654
    for (i = 0; i < _mapping_from.length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3655
      for (j = i + 1; j < _mapping_from.length(); j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3656
        assert(_mapping_from.at(i) == NULL || _mapping_from.at(i) != _mapping_from.at(j), "cannot read from same interval twice");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3657
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3658
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3659
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3660
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3661
  for (i = 0; i < _mapping_to.length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3662
    for (j = i + 1; j < _mapping_to.length(); j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3663
      assert(_mapping_to.at(i) != _mapping_to.at(j), "cannot write to same interval twice");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3664
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3665
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3666
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3667
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3668
  BitMap used_regs(LinearScan::nof_regs + allocator()->frame_map()->argcount() + allocator()->max_spills());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3669
  used_regs.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3670
  if (!_multiple_reads_allowed) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3671
    for (i = 0; i < _mapping_from.length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3672
      Interval* it = _mapping_from.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3673
      if (it != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3674
        assert(!used_regs.at(it->assigned_reg()), "cannot read from same register twice");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3675
        used_regs.set_bit(it->assigned_reg());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3676
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3677
        if (it->assigned_regHi() != LinearScan::any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3678
          assert(!used_regs.at(it->assigned_regHi()), "cannot read from same register twice");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3679
          used_regs.set_bit(it->assigned_regHi());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3680
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3681
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3682
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3683
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3684
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3685
  used_regs.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3686
  for (i = 0; i < _mapping_to.length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3687
    Interval* it = _mapping_to.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3688
    assert(!used_regs.at(it->assigned_reg()), "cannot write to same register twice");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3689
    used_regs.set_bit(it->assigned_reg());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3690
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3691
    if (it->assigned_regHi() != LinearScan::any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3692
      assert(!used_regs.at(it->assigned_regHi()), "cannot write to same register twice");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3693
      used_regs.set_bit(it->assigned_regHi());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3694
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3695
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3696
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3697
  used_regs.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3698
  for (i = 0; i < _mapping_from.length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3699
    Interval* it = _mapping_from.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3700
    if (it != NULL && it->assigned_reg() >= LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3701
      used_regs.set_bit(it->assigned_reg());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3702
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3703
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3704
  for (i = 0; i < _mapping_to.length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3705
    Interval* it = _mapping_to.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3706
    assert(!used_regs.at(it->assigned_reg()) || it->assigned_reg() == _mapping_from.at(i)->assigned_reg(), "stack slots used in _mapping_from must be disjoint to _mapping_to");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3707
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3708
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3709
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3710
#endif // ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3711
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3712
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3713
// mark assigned_reg and assigned_regHi of the interval as blocked
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3714
void MoveResolver::block_registers(Interval* it) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3715
  int reg = it->assigned_reg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3716
  if (reg < LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3717
    assert(_multiple_reads_allowed || register_blocked(reg) == 0, "register already marked as used");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3718
    set_register_blocked(reg, 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3719
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3720
  reg = it->assigned_regHi();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3721
  if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3722
    assert(_multiple_reads_allowed || register_blocked(reg) == 0, "register already marked as used");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3723
    set_register_blocked(reg, 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3724
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3725
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3726
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3727
// mark assigned_reg and assigned_regHi of the interval as unblocked
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3728
void MoveResolver::unblock_registers(Interval* it) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3729
  int reg = it->assigned_reg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3730
  if (reg < LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3731
    assert(register_blocked(reg) > 0, "register already marked as unused");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3732
    set_register_blocked(reg, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3733
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3734
  reg = it->assigned_regHi();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3735
  if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3736
    assert(register_blocked(reg) > 0, "register already marked as unused");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3737
    set_register_blocked(reg, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3738
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3739
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3740
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3741
// check if assigned_reg and assigned_regHi of the to-interval are not blocked (or only blocked by from)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3742
bool MoveResolver::save_to_process_move(Interval* from, Interval* to) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3743
  int from_reg = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3744
  int from_regHi = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3745
  if (from != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3746
    from_reg = from->assigned_reg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3747
    from_regHi = from->assigned_regHi();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3748
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3749
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3750
  int reg = to->assigned_reg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3751
  if (reg < LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3752
    if (register_blocked(reg) > 1 || (register_blocked(reg) == 1 && reg != from_reg && reg != from_regHi)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3753
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3754
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3755
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3756
  reg = to->assigned_regHi();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3757
  if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3758
    if (register_blocked(reg) > 1 || (register_blocked(reg) == 1 && reg != from_reg && reg != from_regHi)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3759
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3760
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3761
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3762
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3763
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3764
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3765
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3766
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3767
void MoveResolver::create_insertion_buffer(LIR_List* list) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3768
  assert(!_insertion_buffer.initialized(), "overwriting existing buffer");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3769
  _insertion_buffer.init(list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3770
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3771
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3772
void MoveResolver::append_insertion_buffer() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3773
  if (_insertion_buffer.initialized()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3774
    _insertion_buffer.lir_list()->append(&_insertion_buffer);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3775
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3776
  assert(!_insertion_buffer.initialized(), "must be uninitialized now");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3777
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3778
  _insert_list = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3779
  _insert_idx = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3780
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3781
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3782
void MoveResolver::insert_move(Interval* from_interval, Interval* to_interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3783
  assert(from_interval->reg_num() != to_interval->reg_num(), "from and to interval equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3784
  assert(from_interval->type() == to_interval->type(), "move between different types");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3785
  assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3786
  assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3787
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3788
  LIR_Opr from_opr = LIR_OprFact::virtual_register(from_interval->reg_num(), from_interval->type());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3789
  LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3790
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3791
  if (!_multiple_reads_allowed) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3792
    // the last_use flag is an optimization for FPU stack allocation. When the same
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3793
    // input interval is used in more than one move, then it is too difficult to determine
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3794
    // if this move is really the last use.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3795
    from_opr = from_opr->make_last_use();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3796
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3797
  _insertion_buffer.move(_insert_idx, from_opr, to_opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3798
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3799
  TRACE_LINEAR_SCAN(4, tty->print_cr("MoveResolver: inserted move from register %d (%d, %d) to %d (%d, %d)", from_interval->reg_num(), from_interval->assigned_reg(), from_interval->assigned_regHi(), to_interval->reg_num(), to_interval->assigned_reg(), to_interval->assigned_regHi()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3800
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3801
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3802
void MoveResolver::insert_move(LIR_Opr from_opr, Interval* to_interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3803
  assert(from_opr->type() == to_interval->type(), "move between different types");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3804
  assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3805
  assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3806
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3807
  LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3808
  _insertion_buffer.move(_insert_idx, from_opr, to_opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3809
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3810
  TRACE_LINEAR_SCAN(4, tty->print("MoveResolver: inserted move from constant "); from_opr->print(); tty->print_cr("  to %d (%d, %d)", to_interval->reg_num(), to_interval->assigned_reg(), to_interval->assigned_regHi()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3811
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3812
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3813
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3814
void MoveResolver::resolve_mappings() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3815
  TRACE_LINEAR_SCAN(4, tty->print_cr("MoveResolver: resolving mappings for Block B%d, index %d", _insert_list->block() != NULL ? _insert_list->block()->block_id() : -1, _insert_idx));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3816
  DEBUG_ONLY(verify_before_resolve());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3817
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3818
  // Block all registers that are used as input operands of a move.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3819
  // When a register is blocked, no move to this register is emitted.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3820
  // This is necessary for detecting cycles in moves.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3821
  int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3822
  for (i = _mapping_from.length() - 1; i >= 0; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3823
    Interval* from_interval = _mapping_from.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3824
    if (from_interval != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3825
      block_registers(from_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3826
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3827
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3828
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3829
  int spill_candidate = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3830
  while (_mapping_from.length() > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3831
    bool processed_interval = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3832
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3833
    for (i = _mapping_from.length() - 1; i >= 0; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3834
      Interval* from_interval = _mapping_from.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3835
      Interval* to_interval = _mapping_to.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3836
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3837
      if (save_to_process_move(from_interval, to_interval)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3838
        // this inverval can be processed because target is free
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3839
        if (from_interval != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3840
          insert_move(from_interval, to_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3841
          unblock_registers(from_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3842
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3843
          insert_move(_mapping_from_opr.at(i), to_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3844
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3845
        _mapping_from.remove_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3846
        _mapping_from_opr.remove_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3847
        _mapping_to.remove_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3848
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3849
        processed_interval = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3850
      } else if (from_interval != NULL && from_interval->assigned_reg() < LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3851
        // this interval cannot be processed now because target is not free
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3852
        // it starts in a register, so it is a possible candidate for spilling
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3853
        spill_candidate = i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3854
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3855
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3856
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3857
    if (!processed_interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3858
      // no move could be processed because there is a cycle in the move list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3859
      // (e.g. r1 -> r2, r2 -> r1), so one interval must be spilled to memory
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3860
      assert(spill_candidate != -1, "no interval in register for spilling found");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3861
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3862
      // create a new spill interval and assign a stack slot to it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3863
      Interval* from_interval = _mapping_from.at(spill_candidate);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3864
      Interval* spill_interval = new Interval(-1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3865
      spill_interval->set_type(from_interval->type());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3866
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3867
      // add a dummy range because real position is difficult to calculate
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3868
      // Note: this range is a special case when the integrity of the allocation is checked
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3869
      spill_interval->add_range(1, 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3870
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3871
      //       do not allocate a new spill slot for temporary interval, but
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3872
      //       use spill slot assigned to from_interval. Otherwise moves from
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3873
      //       one stack slot to another can happen (not allowed by LIR_Assembler
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3874
      int spill_slot = from_interval->canonical_spill_slot();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3875
      if (spill_slot < 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3876
        spill_slot = allocator()->allocate_spill_slot(type2spill_size[spill_interval->type()] == 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3877
        from_interval->set_canonical_spill_slot(spill_slot);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3878
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3879
      spill_interval->assign_reg(spill_slot);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3880
      allocator()->append_interval(spill_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3881
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3882
      TRACE_LINEAR_SCAN(4, tty->print_cr("created new Interval %d for spilling", spill_interval->reg_num()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3883
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3884
      // insert a move from register to stack and update the mapping
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3885
      insert_move(from_interval, spill_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3886
      _mapping_from.at_put(spill_candidate, spill_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3887
      unblock_registers(from_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3888
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3889
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3890
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3891
  // reset to default value
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3892
  _multiple_reads_allowed = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3893
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3894
  // check that all intervals have been processed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3895
  DEBUG_ONLY(check_empty());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3896
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3897
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3898
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3899
void MoveResolver::set_insert_position(LIR_List* insert_list, int insert_idx) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3900
  TRACE_LINEAR_SCAN(4, tty->print_cr("MoveResolver: setting insert position to Block B%d, index %d", insert_list->block() != NULL ? insert_list->block()->block_id() : -1, insert_idx));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3901
  assert(_insert_list == NULL && _insert_idx == -1, "use move_insert_position instead of set_insert_position when data already set");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3902
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3903
  create_insertion_buffer(insert_list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3904
  _insert_list = insert_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3905
  _insert_idx = insert_idx;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3906
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3907
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3908
void MoveResolver::move_insert_position(LIR_List* insert_list, int insert_idx) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3909
  TRACE_LINEAR_SCAN(4, tty->print_cr("MoveResolver: moving insert position to Block B%d, index %d", insert_list->block() != NULL ? insert_list->block()->block_id() : -1, insert_idx));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3910
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3911
  if (_insert_list != NULL && (insert_list != _insert_list || insert_idx != _insert_idx)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3912
    // insert position changed -> resolve current mappings
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3913
    resolve_mappings();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3914
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3915
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3916
  if (insert_list != _insert_list) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3917
    // block changed -> append insertion_buffer because it is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3918
    // bound to a specific block and create a new insertion_buffer
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3919
    append_insertion_buffer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3920
    create_insertion_buffer(insert_list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3921
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3922
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3923
  _insert_list = insert_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3924
  _insert_idx = insert_idx;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3925
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3926
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3927
void MoveResolver::add_mapping(Interval* from_interval, Interval* to_interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3928
  TRACE_LINEAR_SCAN(4, tty->print_cr("MoveResolver: adding mapping from %d (%d, %d) to %d (%d, %d)", from_interval->reg_num(), from_interval->assigned_reg(), from_interval->assigned_regHi(), to_interval->reg_num(), to_interval->assigned_reg(), to_interval->assigned_regHi()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3929
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3930
  _mapping_from.append(from_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3931
  _mapping_from_opr.append(LIR_OprFact::illegalOpr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3932
  _mapping_to.append(to_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3933
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3934
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3935
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3936
void MoveResolver::add_mapping(LIR_Opr from_opr, Interval* to_interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3937
  TRACE_LINEAR_SCAN(4, tty->print("MoveResolver: adding mapping from "); from_opr->print(); tty->print_cr(" to %d (%d, %d)", to_interval->reg_num(), to_interval->assigned_reg(), to_interval->assigned_regHi()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3938
  assert(from_opr->is_constant(), "only for constants");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3939
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3940
  _mapping_from.append(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3941
  _mapping_from_opr.append(from_opr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3942
  _mapping_to.append(to_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3943
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3944
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3945
void MoveResolver::resolve_and_append_moves() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3946
  if (has_mappings()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3947
    resolve_mappings();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3948
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3949
  append_insertion_buffer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3950
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3951
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3952
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3953
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3954
// **** Implementation of Range *************************************
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3955
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3956
Range::Range(int from, int to, Range* next) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3957
  _from(from),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3958
  _to(to),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3959
  _next(next)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3960
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3961
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3962
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3963
// initialize sentinel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3964
Range* Range::_end = NULL;
5707
6c66849ed24e 6958292: C1: Enable parallel compilation
iveresov
parents: 5547
diff changeset
  3965
void Range::initialize(Arena* arena) {
6c66849ed24e 6958292: C1: Enable parallel compilation
iveresov
parents: 5547
diff changeset
  3966
  _end = new (arena) Range(max_jint, max_jint, NULL);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3967
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3968
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3969
int Range::intersects_at(Range* r2) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3970
  const Range* r1 = this;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3971
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3972
  assert(r1 != NULL && r2 != NULL, "null ranges not allowed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3973
  assert(r1 != _end && r2 != _end, "empty ranges not allowed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3974
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3975
  do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3976
    if (r1->from() < r2->from()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3977
      if (r1->to() <= r2->from()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3978
        r1 = r1->next(); if (r1 == _end) return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3979
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3980
        return r2->from();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3981
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3982
    } else if (r2->from() < r1->from()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3983
      if (r2->to() <= r1->from()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3984
        r2 = r2->next(); if (r2 == _end) return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3985
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3986
        return r1->from();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3987
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3988
    } else { // r1->from() == r2->from()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3989
      if (r1->from() == r1->to()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3990
        r1 = r1->next(); if (r1 == _end) return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3991
      } else if (r2->from() == r2->to()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3992
        r2 = r2->next(); if (r2 == _end) return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3993
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3994
        return r1->from();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3995
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3996
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3997
  } while (true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3998
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3999
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4000
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4001
void Range::print(outputStream* out) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4002
  out->print("[%d, %d[ ", _from, _to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4003
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4004
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4005
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4006
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4007
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4008
// **** Implementation of Interval **********************************
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4009
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4010
// initialize sentinel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4011
Interval* Interval::_end = NULL;
5707
6c66849ed24e 6958292: C1: Enable parallel compilation
iveresov
parents: 5547
diff changeset
  4012
void Interval::initialize(Arena* arena) {
6c66849ed24e 6958292: C1: Enable parallel compilation
iveresov
parents: 5547
diff changeset
  4013
  Range::initialize(arena);
6c66849ed24e 6958292: C1: Enable parallel compilation
iveresov
parents: 5547
diff changeset
  4014
  _end = new (arena) Interval(-1);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4015
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4016
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4017
Interval::Interval(int reg_num) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4018
  _reg_num(reg_num),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4019
  _type(T_ILLEGAL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4020
  _first(Range::end()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4021
  _use_pos_and_kinds(12),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4022
  _current(Range::end()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4023
  _next(_end),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4024
  _state(invalidState),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4025
  _assigned_reg(LinearScan::any_reg),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4026
  _assigned_regHi(LinearScan::any_reg),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4027
  _cached_to(-1),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4028
  _cached_opr(LIR_OprFact::illegalOpr),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4029
  _cached_vm_reg(VMRegImpl::Bad()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4030
  _split_children(0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4031
  _canonical_spill_slot(-1),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4032
  _insert_move_when_activated(false),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4033
  _register_hint(NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4034
  _spill_state(noDefinitionFound),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4035
  _spill_definition_pos(-1)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4036
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4037
  _split_parent = this;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4038
  _current_split_child = this;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4039
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4040
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4041
int Interval::calc_to() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4042
  assert(_first != Range::end(), "interval has no range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4043
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4044
  Range* r = _first;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4045
  while (r->next() != Range::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4046
    r = r->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4047
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4048
  return r->to();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4049
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4050
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4051
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4052
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4053
// consistency check of split-children
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4054
void Interval::check_split_children() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4055
  if (_split_children.length() > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4056
    assert(is_split_parent(), "only split parents can have children");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4057
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4058
    for (int i = 0; i < _split_children.length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4059
      Interval* i1 = _split_children.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4060
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4061
      assert(i1->split_parent() == this, "not a split child of this interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4062
      assert(i1->type() == type(), "must be equal for all split children");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4063
      assert(i1->canonical_spill_slot() == canonical_spill_slot(), "must be equal for all split children");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4064
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4065
      for (int j = i + 1; j < _split_children.length(); j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4066
        Interval* i2 = _split_children.at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4067
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4068
        assert(i1->reg_num() != i2->reg_num(), "same register number");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4069
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4070
        if (i1->from() < i2->from()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4071
          assert(i1->to() <= i2->from() && i1->to() < i2->to(), "intervals overlapping");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4072
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4073
          assert(i2->from() < i1->from(), "intervals start at same op_id");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4074
          assert(i2->to() <= i1->from() && i2->to() < i1->to(), "intervals overlapping");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4075
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4076
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4077
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4078
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4079
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4080
#endif // ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4081
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4082
Interval* Interval::register_hint(bool search_split_child) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4083
  if (!search_split_child) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4084
    return _register_hint;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4085
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4086
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4087
  if (_register_hint != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4088
    assert(_register_hint->is_split_parent(), "ony split parents are valid hint registers");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4089
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4090
    if (_register_hint->assigned_reg() >= 0 && _register_hint->assigned_reg() < LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4091
      return _register_hint;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4092
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4093
    } else if (_register_hint->_split_children.length() > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4094
      // search the first split child that has a register assigned
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4095
      int len = _register_hint->_split_children.length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4096
      for (int i = 0; i < len; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4097
        Interval* cur = _register_hint->_split_children.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4098
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4099
        if (cur->assigned_reg() >= 0 && cur->assigned_reg() < LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4100
          return cur;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4101
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4102
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4103
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4104
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4105
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4106
  // no hint interval found that has a register assigned
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4107
  return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4108
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4109
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4110
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4111
Interval* Interval::split_child_at_op_id(int op_id, LIR_OpVisitState::OprMode mode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4112
  assert(is_split_parent(), "can only be called for split parents");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4113
  assert(op_id >= 0, "invalid op_id (method can not be called for spill moves)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4114
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4115
  Interval* result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4116
  if (_split_children.length() == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4117
    result = this;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4118
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4119
    result = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4120
    int len = _split_children.length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4121
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4122
    // in outputMode, the end of the interval (op_id == cur->to()) is not valid
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4123
    int to_offset = (mode == LIR_OpVisitState::outputMode ? 0 : 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4124
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4125
    int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4126
    for (i = 0; i < len; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4127
      Interval* cur = _split_children.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4128
      if (cur->from() <= op_id && op_id < cur->to() + to_offset) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4129
        if (i > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4130
          // exchange current split child to start of list (faster access for next call)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4131
          _split_children.at_put(i, _split_children.at(0));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4132
          _split_children.at_put(0, cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4133
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4134
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4135
        // interval found
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4136
        result = cur;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4137
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4138
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4139
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4140
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4141
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4142
    for (i = 0; i < len; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4143
      Interval* tmp = _split_children.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4144
      if (tmp != result && tmp->from() <= op_id && op_id < tmp->to() + to_offset) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4145
        tty->print_cr("two valid result intervals found for op_id %d: %d and %d", op_id, result->reg_num(), tmp->reg_num());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4146
        result->print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4147
        tmp->print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4148
        assert(false, "two valid result intervals found");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4149
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4150
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4151
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4152
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4153
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4154
  assert(result != NULL, "no matching interval found");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4155
  assert(result->covers(op_id, mode), "op_id not covered by interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4156
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4157
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4158
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4159
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4160
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4161
// returns the last split child that ends before the given op_id
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4162
Interval* Interval::split_child_before_op_id(int op_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4163
  assert(op_id >= 0, "invalid op_id");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4164
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4165
  Interval* parent = split_parent();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4166
  Interval* result = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4167
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4168
  int len = parent->_split_children.length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4169
  assert(len > 0, "no split children available");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4170
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4171
  for (int i = len - 1; i >= 0; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4172
    Interval* cur = parent->_split_children.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4173
    if (cur->to() <= op_id && (result == NULL || result->to() < cur->to())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4174
      result = cur;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4175
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4176
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4177
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4178
  assert(result != NULL, "no split child found");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4179
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4180
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4181
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4182
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4183
// checks if op_id is covered by any split child
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4184
bool Interval::split_child_covers(int op_id, LIR_OpVisitState::OprMode mode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4185
  assert(is_split_parent(), "can only be called for split parents");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4186
  assert(op_id >= 0, "invalid op_id (method can not be called for spill moves)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4187
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4188
  if (_split_children.length() == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4189
    // simple case if interval was not split
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4190
    return covers(op_id, mode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4191
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4192
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4193
    // extended case: check all split children
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4194
    int len = _split_children.length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4195
    for (int i = 0; i < len; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4196
      Interval* cur = _split_children.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4197
      if (cur->covers(op_id, mode)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4198
        return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4199
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4200
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4201
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4202
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4203
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4204
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4205
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4206
// Note: use positions are sorted descending -> first use has highest index
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4207
int Interval::first_usage(IntervalUseKind min_use_kind) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4208
  assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4209
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4210
  for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4211
    if (_use_pos_and_kinds.at(i + 1) >= min_use_kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4212
      return _use_pos_and_kinds.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4213
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4214
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4215
  return max_jint;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4216
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4217
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4218
int Interval::next_usage(IntervalUseKind min_use_kind, int from) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4219
  assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4220
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4221
  for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4222
    if (_use_pos_and_kinds.at(i) >= from && _use_pos_and_kinds.at(i + 1) >= min_use_kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4223
      return _use_pos_and_kinds.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4224
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4225
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4226
  return max_jint;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4227
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4228
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4229
int Interval::next_usage_exact(IntervalUseKind exact_use_kind, int from) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4230
  assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4231
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4232
  for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4233
    if (_use_pos_and_kinds.at(i) >= from && _use_pos_and_kinds.at(i + 1) == exact_use_kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4234
      return _use_pos_and_kinds.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4235
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4236
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4237
  return max_jint;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4238
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4239
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4240
int Interval::previous_usage(IntervalUseKind min_use_kind, int from) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4241
  assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4242
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4243
  int prev = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4244
  for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4245
    if (_use_pos_and_kinds.at(i) > from) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4246
      return prev;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4247
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4248
    if (_use_pos_and_kinds.at(i + 1) >= min_use_kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4249
      prev = _use_pos_and_kinds.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4250
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4251
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4252
  return prev;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4253
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4254
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4255
void Interval::add_use_pos(int pos, IntervalUseKind use_kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4256
  assert(covers(pos, LIR_OpVisitState::inputMode), "use position not covered by live range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4257
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4258
  // do not add use positions for precolored intervals because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4259
  // they are never used
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4260
  if (use_kind != noUse && reg_num() >= LIR_OprDesc::vreg_base) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4261
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4262
    assert(_use_pos_and_kinds.length() % 2 == 0, "must be");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4263
    for (int i = 0; i < _use_pos_and_kinds.length(); i += 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4264
      assert(pos <= _use_pos_and_kinds.at(i), "already added a use-position with lower position");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4265
      assert(_use_pos_and_kinds.at(i + 1) >= firstValidKind && _use_pos_and_kinds.at(i + 1) <= lastValidKind, "invalid use kind");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4266
      if (i > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4267
        assert(_use_pos_and_kinds.at(i) < _use_pos_and_kinds.at(i - 2), "not sorted descending");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4268
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4269
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4270
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4271
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4272
    // Note: add_use is called in descending order, so list gets sorted
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4273
    //       automatically by just appending new use positions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4274
    int len = _use_pos_and_kinds.length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4275
    if (len == 0 || _use_pos_and_kinds.at(len - 2) > pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4276
      _use_pos_and_kinds.append(pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4277
      _use_pos_and_kinds.append(use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4278
    } else if (_use_pos_and_kinds.at(len - 1) < use_kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4279
      assert(_use_pos_and_kinds.at(len - 2) == pos, "list not sorted correctly");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4280
      _use_pos_and_kinds.at_put(len - 1, use_kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4281
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4282
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4283
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4284
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4285
void Interval::add_range(int from, int to) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4286
  assert(from < to, "invalid range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4287
  assert(first() == Range::end() || to < first()->next()->from(), "not inserting at begin of interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4288
  assert(from <= first()->to(), "not inserting at begin of interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4289
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4290
  if (first()->from() <= to) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4291
    // join intersecting ranges
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4292
    first()->set_from(MIN2(from, first()->from()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4293
    first()->set_to  (MAX2(to,   first()->to()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4294
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4295
    // insert new range
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4296
    _first = new Range(from, to, first());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4297
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4298
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4299
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4300
Interval* Interval::new_split_child() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4301
  // allocate new interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4302
  Interval* result = new Interval(-1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4303
  result->set_type(type());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4304
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4305
  Interval* parent = split_parent();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4306
  result->_split_parent = parent;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4307
  result->set_register_hint(parent);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4308
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4309
  // insert new interval in children-list of parent
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4310
  if (parent->_split_children.length() == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4311
    assert(is_split_parent(), "list must be initialized at first split");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4312
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4313
    parent->_split_children = IntervalList(4);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4314
    parent->_split_children.append(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4315
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4316
  parent->_split_children.append(result);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4317
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4318
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4319
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4320
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4321
// split this interval at the specified position and return
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4322
// the remainder as a new interval.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4323
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4324
// when an interval is split, a bi-directional link is established between the original interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4325
// (the split parent) and the intervals that are split off this interval (the split children)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4326
// When a split child is split again, the new created interval is also a direct child
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4327
// of the original parent (there is no tree of split children stored, but a flat list)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4328
// All split children are spilled to the same stack slot (stored in _canonical_spill_slot)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4329
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4330
// Note: The new interval has no valid reg_num
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4331
Interval* Interval::split(int split_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4332
  assert(LinearScan::is_virtual_interval(this), "cannot split fixed intervals");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4333
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4334
  // allocate new interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4335
  Interval* result = new_split_child();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4336
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4337
  // split the ranges
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4338
  Range* prev = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4339
  Range* cur = _first;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4340
  while (cur != Range::end() && cur->to() <= split_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4341
    prev = cur;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4342
    cur = cur->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4343
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4344
  assert(cur != Range::end(), "split interval after end of last range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4345
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4346
  if (cur->from() < split_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4347
    result->_first = new Range(split_pos, cur->to(), cur->next());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4348
    cur->set_to(split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4349
    cur->set_next(Range::end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4350
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4351
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4352
    assert(prev != NULL, "split before start of first range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4353
    result->_first = cur;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4354
    prev->set_next(Range::end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4355
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4356
  result->_current = result->_first;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4357
  _cached_to = -1; // clear cached value
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4358
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4359
  // split list of use positions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4360
  int total_len = _use_pos_and_kinds.length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4361
  int start_idx = total_len - 2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4362
  while (start_idx >= 0 && _use_pos_and_kinds.at(start_idx) < split_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4363
    start_idx -= 2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4364
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4365
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4366
  intStack new_use_pos_and_kinds(total_len - start_idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4367
  int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4368
  for (i = start_idx + 2; i < total_len; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4369
    new_use_pos_and_kinds.append(_use_pos_and_kinds.at(i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4370
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4371
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4372
  _use_pos_and_kinds.truncate(start_idx + 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4373
  result->_use_pos_and_kinds = _use_pos_and_kinds;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4374
  _use_pos_and_kinds = new_use_pos_and_kinds;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4375
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4376
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4377
  assert(_use_pos_and_kinds.length() % 2 == 0, "must have use kind for each use pos");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4378
  assert(result->_use_pos_and_kinds.length() % 2 == 0, "must have use kind for each use pos");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4379
  assert(_use_pos_and_kinds.length() + result->_use_pos_and_kinds.length() == total_len, "missed some entries");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4380
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4381
  for (i = 0; i < _use_pos_and_kinds.length(); i += 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4382
    assert(_use_pos_and_kinds.at(i) < split_pos, "must be");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4383
    assert(_use_pos_and_kinds.at(i + 1) >= firstValidKind && _use_pos_and_kinds.at(i + 1) <= lastValidKind, "invalid use kind");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4384
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4385
  for (i = 0; i < result->_use_pos_and_kinds.length(); i += 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4386
    assert(result->_use_pos_and_kinds.at(i) >= split_pos, "must be");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4387
    assert(result->_use_pos_and_kinds.at(i + 1) >= firstValidKind && result->_use_pos_and_kinds.at(i + 1) <= lastValidKind, "invalid use kind");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4388
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4389
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4390
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4391
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4392
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4393
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4394
// split this interval at the specified position and return
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4395
// the head as a new interval (the original interval is the tail)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4396
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4397
// Currently, only the first range can be split, and the new interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4398
// must not have split positions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4399
Interval* Interval::split_from_start(int split_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4400
  assert(LinearScan::is_virtual_interval(this), "cannot split fixed intervals");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4401
  assert(split_pos > from() && split_pos < to(), "can only split inside interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4402
  assert(split_pos > _first->from() && split_pos <= _first->to(), "can only split inside first range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4403
  assert(first_usage(noUse) > split_pos, "can not split when use positions are present");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4404
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4405
  // allocate new interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4406
  Interval* result = new_split_child();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4407
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4408
  // the new created interval has only one range (checked by assertion above),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4409
  // so the splitting of the ranges is very simple
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4410
  result->add_range(_first->from(), split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4411
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4412
  if (split_pos == _first->to()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4413
    assert(_first->next() != Range::end(), "must not be at end");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4414
    _first = _first->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4415
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4416
    _first->set_from(split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4417
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4418
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4419
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4420
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4421
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4422
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4423
// returns true if the op_id is inside the interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4424
bool Interval::covers(int op_id, LIR_OpVisitState::OprMode mode) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4425
  Range* cur  = _first;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4426
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4427
  while (cur != Range::end() && cur->to() < op_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4428
    cur = cur->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4429
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4430
  if (cur != Range::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4431
    assert(cur->to() != cur->next()->from(), "ranges not separated");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4432
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4433
    if (mode == LIR_OpVisitState::outputMode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4434
      return cur->from() <= op_id && op_id < cur->to();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4435
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4436
      return cur->from() <= op_id && op_id <= cur->to();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4437
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4438
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4439
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4440
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4441
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4442
// returns true if the interval has any hole between hole_from and hole_to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4443
// (even if the hole has only the length 1)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4444
bool Interval::has_hole_between(int hole_from, int hole_to) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4445
  assert(hole_from < hole_to, "check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4446
  assert(from() <= hole_from && hole_to <= to(), "index out of interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4447
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4448
  Range* cur  = _first;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4449
  while (cur != Range::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4450
    assert(cur->to() < cur->next()->from(), "no space between ranges");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4451
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4452
    // hole-range starts before this range -> hole
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4453
    if (hole_from < cur->from()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4454
      return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4455
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4456
    // hole-range completely inside this range -> no hole
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4457
    } else if (hole_to <= cur->to()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4458
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4459
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4460
    // overlapping of hole-range with this range -> hole
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4461
    } else if (hole_from <= cur->to()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4462
      return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4463
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4464
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4465
    cur = cur->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4466
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4467
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4468
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4469
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4470
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4471
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4472
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4473
void Interval::print(outputStream* out) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4474
  const char* SpillState2Name[] = { "no definition", "no spill store", "one spill store", "store at definition", "start in memory", "no optimization" };
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4475
  const char* UseKind2Name[] = { "N", "L", "S", "M" };
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4476
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4477
  const char* type_name;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4478
  LIR_Opr opr = LIR_OprFact::illegal();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4479
  if (reg_num() < LIR_OprDesc::vreg_base) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4480
    type_name = "fixed";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4481
    // need a temporary operand for fixed intervals because type() cannot be called
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4482
    if (assigned_reg() >= pd_first_cpu_reg && assigned_reg() <= pd_last_cpu_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4483
      opr = LIR_OprFact::single_cpu(assigned_reg());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4484
    } else if (assigned_reg() >= pd_first_fpu_reg && assigned_reg() <= pd_last_fpu_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4485
      opr = LIR_OprFact::single_fpu(assigned_reg() - pd_first_fpu_reg);
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  4486
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4487
    } else if (assigned_reg() >= pd_first_xmm_reg && assigned_reg() <= pd_last_xmm_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4488
      opr = LIR_OprFact::single_xmm(assigned_reg() - pd_first_xmm_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4489
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4490
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4491
      ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4492
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4493
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4494
    type_name = type2name(type());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4495
    if (assigned_reg() != -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4496
      opr = LinearScan::calc_operand_for_interval(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4497
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4498
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4499
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4500
  out->print("%d %s ", reg_num(), type_name);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4501
  if (opr->is_valid()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4502
    out->print("\"");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4503
    opr->print(out);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4504
    out->print("\" ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4505
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4506
  out->print("%d %d ", split_parent()->reg_num(), (register_hint(false) != NULL ? register_hint(false)->reg_num() : -1));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4507
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4508
  // print ranges
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4509
  Range* cur = _first;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4510
  while (cur != Range::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4511
    cur->print(out);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4512
    cur = cur->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4513
    assert(cur != NULL, "range list not closed with range sentinel");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4514
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4515
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4516
  // print use positions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4517
  int prev = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4518
  assert(_use_pos_and_kinds.length() % 2 == 0, "must be");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4519
  for (int i =_use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4520
    assert(_use_pos_and_kinds.at(i + 1) >= firstValidKind && _use_pos_and_kinds.at(i + 1) <= lastValidKind, "invalid use kind");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4521
    assert(prev < _use_pos_and_kinds.at(i), "use positions not sorted");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4522
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4523
    out->print("%d %s ", _use_pos_and_kinds.at(i), UseKind2Name[_use_pos_and_kinds.at(i + 1)]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4524
    prev = _use_pos_and_kinds.at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4525
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4526
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4527
  out->print(" \"%s\"", SpillState2Name[spill_state()]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4528
  out->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4529
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4530
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4531
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4532
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4533
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4534
// **** Implementation of IntervalWalker ****************************
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4535
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4536
IntervalWalker::IntervalWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4537
 : _compilation(allocator->compilation())
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4538
 , _allocator(allocator)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4539
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4540
  _unhandled_first[fixedKind] = unhandled_fixed_first;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4541
  _unhandled_first[anyKind]   = unhandled_any_first;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4542
  _active_first[fixedKind]    = Interval::end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4543
  _inactive_first[fixedKind]  = Interval::end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4544
  _active_first[anyKind]      = Interval::end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4545
  _inactive_first[anyKind]    = Interval::end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4546
  _current_position = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4547
  _current = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4548
  next_interval();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4549
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4550
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4551
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4552
// append interval at top of list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4553
void IntervalWalker::append_unsorted(Interval** list, Interval* interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4554
  interval->set_next(*list); *list = interval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4555
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4556
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4557
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4558
// append interval in order of current range from()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4559
void IntervalWalker::append_sorted(Interval** list, Interval* interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4560
  Interval* prev = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4561
  Interval* cur  = *list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4562
  while (cur->current_from() < interval->current_from()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4563
    prev = cur; cur = cur->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4564
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4565
  if (prev == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4566
    *list = interval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4567
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4568
    prev->set_next(interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4569
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4570
  interval->set_next(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4571
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4572
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4573
void IntervalWalker::append_to_unhandled(Interval** list, Interval* interval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4574
  assert(interval->from() >= current()->current_from(), "cannot append new interval before current walk position");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4575
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4576
  Interval* prev = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4577
  Interval* cur  = *list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4578
  while (cur->from() < interval->from() || (cur->from() == interval->from() && cur->first_usage(noUse) < interval->first_usage(noUse))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4579
    prev = cur; cur = cur->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4580
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4581
  if (prev == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4582
    *list = interval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4583
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4584
    prev->set_next(interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4585
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4586
  interval->set_next(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4587
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4588
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4589
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4590
inline bool IntervalWalker::remove_from_list(Interval** list, Interval* i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4591
  while (*list != Interval::end() && *list != i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4592
    list = (*list)->next_addr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4593
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4594
  if (*list != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4595
    assert(*list == i, "check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4596
    *list = (*list)->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4597
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4598
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4599
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4600
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4601
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4602
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4603
void IntervalWalker::remove_from_list(Interval* i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4604
  bool deleted;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4605
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4606
  if (i->state() == activeState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4607
    deleted = remove_from_list(active_first_addr(anyKind), i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4608
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4609
    assert(i->state() == inactiveState, "invalid state");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4610
    deleted = remove_from_list(inactive_first_addr(anyKind), i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4611
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4612
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4613
  assert(deleted, "interval has not been found in list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4614
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4615
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4616
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4617
void IntervalWalker::walk_to(IntervalState state, int from) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4618
  assert (state == activeState || state == inactiveState, "wrong state");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4619
  for_each_interval_kind(kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4620
    Interval** prev = state == activeState ? active_first_addr(kind) : inactive_first_addr(kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4621
    Interval* next   = *prev;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4622
    while (next->current_from() <= from) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4623
      Interval* cur = next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4624
      next = cur->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4625
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4626
      bool range_has_changed = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4627
      while (cur->current_to() <= from) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4628
        cur->next_range();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4629
        range_has_changed = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4630
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4631
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4632
      // also handle move from inactive list to active list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4633
      range_has_changed = range_has_changed || (state == inactiveState && cur->current_from() <= from);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4634
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4635
      if (range_has_changed) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4636
        // remove cur from list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4637
        *prev = next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4638
        if (cur->current_at_end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4639
          // move to handled state (not maintained as a list)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4640
          cur->set_state(handledState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4641
          interval_moved(cur, kind, state, handledState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4642
        } else if (cur->current_from() <= from){
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4643
          // sort into active list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4644
          append_sorted(active_first_addr(kind), cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4645
          cur->set_state(activeState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4646
          if (*prev == cur) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4647
            assert(state == activeState, "check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4648
            prev = cur->next_addr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4649
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4650
          interval_moved(cur, kind, state, activeState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4651
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4652
          // sort into inactive list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4653
          append_sorted(inactive_first_addr(kind), cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4654
          cur->set_state(inactiveState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4655
          if (*prev == cur) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4656
            assert(state == inactiveState, "check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4657
            prev = cur->next_addr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4658
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4659
          interval_moved(cur, kind, state, inactiveState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4660
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4661
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4662
        prev = cur->next_addr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4663
        continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4664
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4665
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4666
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4667
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4668
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4669
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4670
void IntervalWalker::next_interval() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4671
  IntervalKind kind;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4672
  Interval* any   = _unhandled_first[anyKind];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4673
  Interval* fixed = _unhandled_first[fixedKind];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4674
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4675
  if (any != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4676
    // intervals may start at same position -> prefer fixed interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4677
    kind = fixed != Interval::end() && fixed->from() <= any->from() ? fixedKind : anyKind;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4678
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4679
    assert (kind == fixedKind && fixed->from() <= any->from() ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4680
            kind == anyKind   && any->from() <= fixed->from(), "wrong interval!!!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4681
    assert(any == Interval::end() || fixed == Interval::end() || any->from() != fixed->from() || kind == fixedKind, "if fixed and any-Interval start at same position, fixed must be processed first");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4682
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4683
  } else if (fixed != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4684
    kind = fixedKind;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4685
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4686
    _current = NULL; return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4687
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4688
  _current_kind = kind;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4689
  _current = _unhandled_first[kind];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4690
  _unhandled_first[kind] = _current->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4691
  _current->set_next(Interval::end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4692
  _current->rewind_range();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4693
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4694
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4695
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4696
void IntervalWalker::walk_to(int lir_op_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4697
  assert(_current_position <= lir_op_id, "can not walk backwards");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4698
  while (current() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4699
    bool is_active = current()->from() <= lir_op_id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4700
    int id = is_active ? current()->from() : lir_op_id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4701
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4702
    TRACE_LINEAR_SCAN(2, if (_current_position < id) { tty->cr(); tty->print_cr("walk_to(%d) **************************************************************", id); })
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4703
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4704
    // set _current_position prior to call of walk_to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4705
    _current_position = id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4706
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4707
    // call walk_to even if _current_position == id
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4708
    walk_to(activeState, id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4709
    walk_to(inactiveState, id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4710
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4711
    if (is_active) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4712
      current()->set_state(activeState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4713
      if (activate_current()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4714
        append_sorted(active_first_addr(current_kind()), current());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4715
        interval_moved(current(), current_kind(), unhandledState, activeState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4716
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4717
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4718
      next_interval();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4719
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4720
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4721
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4722
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4723
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4724
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4725
void IntervalWalker::interval_moved(Interval* interval, IntervalKind kind, IntervalState from, IntervalState to) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4726
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4727
  if (TraceLinearScanLevel >= 4) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4728
    #define print_state(state) \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4729
    switch(state) {\
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4730
      case unhandledState: tty->print("unhandled"); break;\
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4731
      case activeState: tty->print("active"); break;\
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4732
      case inactiveState: tty->print("inactive"); break;\
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4733
      case handledState: tty->print("handled"); break;\
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4734
      default: ShouldNotReachHere(); \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4735
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4736
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4737
    print_state(from); tty->print(" to "); print_state(to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4738
    tty->fill_to(23);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4739
    interval->print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4740
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4741
    #undef print_state
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4742
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4743
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4744
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4745
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4746
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4747
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4748
// **** Implementation of LinearScanWalker **************************
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4749
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4750
LinearScanWalker::LinearScanWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4751
  : IntervalWalker(allocator, unhandled_fixed_first, unhandled_any_first)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4752
  , _move_resolver(allocator)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4753
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4754
  for (int i = 0; i < LinearScan::nof_regs; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4755
    _spill_intervals[i] = new IntervalList(2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4756
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4757
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4758
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4759
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4760
inline void LinearScanWalker::init_use_lists(bool only_process_use_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4761
  for (int i = _first_reg; i <= _last_reg; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4762
    _use_pos[i] = max_jint;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4763
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4764
    if (!only_process_use_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4765
      _block_pos[i] = max_jint;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4766
      _spill_intervals[i]->clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4767
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4768
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4769
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4770
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4771
inline void LinearScanWalker::exclude_from_use(int reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4772
  assert(reg < LinearScan::nof_regs, "interval must have a register assigned (stack slots not allowed)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4773
  if (reg >= _first_reg && reg <= _last_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4774
    _use_pos[reg] = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4775
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4776
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4777
inline void LinearScanWalker::exclude_from_use(Interval* i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4778
  assert(i->assigned_reg() != any_reg, "interval has no register assigned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4779
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4780
  exclude_from_use(i->assigned_reg());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4781
  exclude_from_use(i->assigned_regHi());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4782
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4783
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4784
inline void LinearScanWalker::set_use_pos(int reg, Interval* i, int use_pos, bool only_process_use_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4785
  assert(use_pos != 0, "must use exclude_from_use to set use_pos to 0");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4786
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4787
  if (reg >= _first_reg && reg <= _last_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4788
    if (_use_pos[reg] > use_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4789
      _use_pos[reg] = use_pos;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4790
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4791
    if (!only_process_use_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4792
      _spill_intervals[reg]->append(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4793
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4794
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4795
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4796
inline void LinearScanWalker::set_use_pos(Interval* i, int use_pos, bool only_process_use_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4797
  assert(i->assigned_reg() != any_reg, "interval has no register assigned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4798
  if (use_pos != -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4799
    set_use_pos(i->assigned_reg(), i, use_pos, only_process_use_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4800
    set_use_pos(i->assigned_regHi(), i, use_pos, only_process_use_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4801
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4802
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4803
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4804
inline void LinearScanWalker::set_block_pos(int reg, Interval* i, int block_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4805
  if (reg >= _first_reg && reg <= _last_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4806
    if (_block_pos[reg] > block_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4807
      _block_pos[reg] = block_pos;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4808
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4809
    if (_use_pos[reg] > block_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4810
      _use_pos[reg] = block_pos;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4811
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4812
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4813
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4814
inline void LinearScanWalker::set_block_pos(Interval* i, int block_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4815
  assert(i->assigned_reg() != any_reg, "interval has no register assigned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4816
  if (block_pos != -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4817
    set_block_pos(i->assigned_reg(), i, block_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4818
    set_block_pos(i->assigned_regHi(), i, block_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4819
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4820
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4821
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4822
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4823
void LinearScanWalker::free_exclude_active_fixed() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4824
  Interval* list = active_first(fixedKind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4825
  while (list != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4826
    assert(list->assigned_reg() < LinearScan::nof_regs, "active interval must have a register assigned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4827
    exclude_from_use(list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4828
    list = list->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4829
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4830
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4831
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4832
void LinearScanWalker::free_exclude_active_any() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4833
  Interval* list = active_first(anyKind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4834
  while (list != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4835
    exclude_from_use(list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4836
    list = list->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4837
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4838
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4839
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4840
void LinearScanWalker::free_collect_inactive_fixed(Interval* cur) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4841
  Interval* list = inactive_first(fixedKind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4842
  while (list != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4843
    if (cur->to() <= list->current_from()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4844
      assert(list->current_intersects_at(cur) == -1, "must not intersect");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4845
      set_use_pos(list, list->current_from(), true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4846
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4847
      set_use_pos(list, list->current_intersects_at(cur), true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4848
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4849
    list = list->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4850
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4851
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4852
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4853
void LinearScanWalker::free_collect_inactive_any(Interval* cur) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4854
  Interval* list = inactive_first(anyKind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4855
  while (list != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4856
    set_use_pos(list, list->current_intersects_at(cur), true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4857
    list = list->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4858
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4859
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4860
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4861
void LinearScanWalker::free_collect_unhandled(IntervalKind kind, Interval* cur) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4862
  Interval* list = unhandled_first(kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4863
  while (list != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4864
    set_use_pos(list, list->intersects_at(cur), true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4865
    if (kind == fixedKind && cur->to() <= list->from()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4866
      set_use_pos(list, list->from(), true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4867
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4868
    list = list->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4869
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4870
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4871
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4872
void LinearScanWalker::spill_exclude_active_fixed() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4873
  Interval* list = active_first(fixedKind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4874
  while (list != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4875
    exclude_from_use(list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4876
    list = list->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4877
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4878
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4879
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4880
void LinearScanWalker::spill_block_unhandled_fixed(Interval* cur) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4881
  Interval* list = unhandled_first(fixedKind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4882
  while (list != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4883
    set_block_pos(list, list->intersects_at(cur));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4884
    list = list->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4885
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4886
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4887
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4888
void LinearScanWalker::spill_block_inactive_fixed(Interval* cur) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4889
  Interval* list = inactive_first(fixedKind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4890
  while (list != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4891
    if (cur->to() > list->current_from()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4892
      set_block_pos(list, list->current_intersects_at(cur));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4893
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4894
      assert(list->current_intersects_at(cur) == -1, "invalid optimization: intervals intersect");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4895
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4896
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4897
    list = list->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4898
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4899
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4900
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4901
void LinearScanWalker::spill_collect_active_any() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4902
  Interval* list = active_first(anyKind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4903
  while (list != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4904
    set_use_pos(list, MIN2(list->next_usage(loopEndMarker, _current_position), list->to()), false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4905
    list = list->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4906
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4907
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4908
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4909
void LinearScanWalker::spill_collect_inactive_any(Interval* cur) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4910
  Interval* list = inactive_first(anyKind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4911
  while (list != Interval::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4912
    if (list->current_intersects(cur)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4913
      set_use_pos(list, MIN2(list->next_usage(loopEndMarker, _current_position), list->to()), false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4914
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4915
    list = list->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4916
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4917
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4918
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4919
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4920
void LinearScanWalker::insert_move(int op_id, Interval* src_it, Interval* dst_it) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4921
  // output all moves here. When source and target are equal, the move is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4922
  // optimized away later in assign_reg_nums
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4923
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4924
  op_id = (op_id + 1) & ~1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4925
  BlockBegin* op_block = allocator()->block_of_op_with_id(op_id);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4926
  assert(op_id > 0 && allocator()->block_of_op_with_id(op_id - 2) == op_block, "cannot insert move at block boundary");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4927
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4928
  // calculate index of instruction inside instruction list of current block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4929
  // the minimal index (for a block with no spill moves) can be calculated because the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4930
  // numbering of instructions is known.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4931
  // When the block already contains spill moves, the index must be increased until the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4932
  // correct index is reached.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4933
  LIR_OpList* list = op_block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4934
  int index = (op_id - list->at(0)->id()) / 2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4935
  assert(list->at(index)->id() <= op_id, "error in calculation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4936
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4937
  while (list->at(index)->id() != op_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4938
    index++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4939
    assert(0 <= index && index < list->length(), "index out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4940
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4941
  assert(1 <= index && index < list->length(), "index out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4942
  assert(list->at(index)->id() == op_id, "error in calculation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4943
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4944
  // insert new instruction before instruction at position index
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4945
  _move_resolver.move_insert_position(op_block->lir(), index - 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4946
  _move_resolver.add_mapping(src_it, dst_it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4947
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4948
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4949
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4950
int LinearScanWalker::find_optimal_split_pos(BlockBegin* min_block, BlockBegin* max_block, int max_split_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4951
  int from_block_nr = min_block->linear_scan_number();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4952
  int to_block_nr = max_block->linear_scan_number();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4953
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4954
  assert(0 <= from_block_nr && from_block_nr < block_count(), "out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4955
  assert(0 <= to_block_nr && to_block_nr < block_count(), "out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4956
  assert(from_block_nr < to_block_nr, "must cross block boundary");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4957
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4958
  // Try to split at end of max_block. If this would be after
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4959
  // max_split_pos, then use the begin of max_block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4960
  int optimal_split_pos = max_block->last_lir_instruction_id() + 2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4961
  if (optimal_split_pos > max_split_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4962
    optimal_split_pos = max_block->first_lir_instruction_id();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4963
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4964
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4965
  int min_loop_depth = max_block->loop_depth();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4966
  for (int i = to_block_nr - 1; i >= from_block_nr; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4967
    BlockBegin* cur = block_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4968
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4969
    if (cur->loop_depth() < min_loop_depth) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4970
      // block with lower loop-depth found -> split at the end of this block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4971
      min_loop_depth = cur->loop_depth();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4972
      optimal_split_pos = cur->last_lir_instruction_id() + 2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4973
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4974
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4975
  assert(optimal_split_pos > allocator()->max_lir_op_id() || allocator()->is_block_begin(optimal_split_pos), "algorithm must move split pos to block boundary");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4976
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4977
  return optimal_split_pos;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4978
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4979
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4980
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4981
int LinearScanWalker::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
  4982
  int optimal_split_pos = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4983
  if (min_split_pos == max_split_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4984
    // trivial case, no optimization of split position possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4985
    TRACE_LINEAR_SCAN(4, tty->print_cr("      min-pos and max-pos are equal, no optimization possible"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4986
    optimal_split_pos = min_split_pos;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4987
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4988
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4989
    assert(min_split_pos < max_split_pos, "must be true then");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4990
    assert(min_split_pos > 0, "cannot access min_split_pos - 1 otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4991
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4992
    // reason for using min_split_pos - 1: when the minimal split pos is exactly at the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4993
    // beginning of a block, then min_split_pos is also a possible split position.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4994
    // Use the block before as min_block, because then min_block->last_lir_instruction_id() + 2 == min_split_pos
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4995
    BlockBegin* min_block = allocator()->block_of_op_with_id(min_split_pos - 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4996
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4997
    // reason for using max_split_pos - 1: otherwise there would be an assertion failure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4998
    // when an interval ends at the end of the last block of the method
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4999
    // (in this case, max_split_pos == allocator()->max_lir_op_id() + 2, and there is no
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5000
    // block at this op_id)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5001
    BlockBegin* max_block = allocator()->block_of_op_with_id(max_split_pos - 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5002
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5003
    assert(min_block->linear_scan_number() <= max_block->linear_scan_number(), "invalid order");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5004
    if (min_block == max_block) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5005
      // split position cannot be moved to block boundary, so split as late as possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5006
      TRACE_LINEAR_SCAN(4, tty->print_cr("      cannot move split pos to block boundary because min_pos and max_pos are in same block"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5007
      optimal_split_pos = max_split_pos;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5008
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5009
    } else if (it->has_hole_between(max_split_pos - 1, max_split_pos) && !allocator()->is_block_begin(max_split_pos)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5010
      // Do not move split position if the interval has a hole before max_split_pos.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5011
      // Intervals resulting from Phi-Functions have more than one definition (marked
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5012
      // as mustHaveRegister) with a hole before each definition. When the register is needed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5013
      // for the second definition, an earlier reloading is unnecessary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5014
      TRACE_LINEAR_SCAN(4, tty->print_cr("      interval has hole just before max_split_pos, so splitting at max_split_pos"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5015
      optimal_split_pos = max_split_pos;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5016
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5017
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5018
      // seach optimal block boundary between min_split_pos and max_split_pos
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5019
      TRACE_LINEAR_SCAN(4, tty->print_cr("      moving split pos to optimal block boundary between block B%d and B%d", min_block->block_id(), max_block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5020
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5021
      if (do_loop_optimization) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5022
        // Loop optimization: if a loop-end marker is found between min- and max-position,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5023
        // then split before this loop
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5024
        int loop_end_pos = it->next_usage_exact(loopEndMarker, min_block->last_lir_instruction_id() + 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5025
        TRACE_LINEAR_SCAN(4, tty->print_cr("      loop optimization: loop end found at pos %d", loop_end_pos));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5026
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5027
        assert(loop_end_pos > min_split_pos, "invalid order");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5028
        if (loop_end_pos < max_split_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5029
          // loop-end marker found between min- and max-position
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5030
          // if it is not the end marker for the same loop as the min-position, then move
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5031
          // the max-position to this loop block.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5032
          // Desired result: uses tagged as shouldHaveRegister inside a loop cause a reloading
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5033
          // of the interval (normally, only mustHaveRegister causes a reloading)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5034
          BlockBegin* loop_block = allocator()->block_of_op_with_id(loop_end_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5035
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5036
          TRACE_LINEAR_SCAN(4, tty->print_cr("      interval is used in loop that ends in block B%d, so trying to move max_block back from B%d to B%d", loop_block->block_id(), max_block->block_id(), loop_block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5037
          assert(loop_block != min_block, "loop_block and min_block must be different because block boundary is needed between");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5038
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5039
          optimal_split_pos = find_optimal_split_pos(min_block, loop_block, loop_block->last_lir_instruction_id() + 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5040
          if (optimal_split_pos == loop_block->last_lir_instruction_id() + 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5041
            optimal_split_pos = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5042
            TRACE_LINEAR_SCAN(4, tty->print_cr("      loop optimization not necessary"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5043
          } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5044
            TRACE_LINEAR_SCAN(4, tty->print_cr("      loop optimization successful"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5045
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5046
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5047
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5048
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5049
      if (optimal_split_pos == -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5050
        // not calculated by loop optimization
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5051
        optimal_split_pos = find_optimal_split_pos(min_block, max_block, max_split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5052
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5053
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5054
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5055
  TRACE_LINEAR_SCAN(4, tty->print_cr("      optimal split position: %d", optimal_split_pos));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5056
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5057
  return optimal_split_pos;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5058
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5059
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5060
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5061
/*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5062
  split an interval at the optimal position between min_split_pos and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5063
  max_split_pos in two parts:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5064
  1) the left part has already a location assigned
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5065
  2) the right part is sorted into to the unhandled-list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5066
*/
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5067
void LinearScanWalker::split_before_usage(Interval* it, int min_split_pos, int max_split_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5068
  TRACE_LINEAR_SCAN(2, tty->print   ("----- splitting interval: "); it->print());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5069
  TRACE_LINEAR_SCAN(2, tty->print_cr("      between %d and %d", min_split_pos, max_split_pos));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5070
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5071
  assert(it->from() < min_split_pos,         "cannot split at start of interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5072
  assert(current_position() < min_split_pos, "cannot split before current position");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5073
  assert(min_split_pos <= max_split_pos,     "invalid order");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5074
  assert(max_split_pos <= it->to(),          "cannot split after end of interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5075
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5076
  int optimal_split_pos = find_optimal_split_pos(it, min_split_pos, max_split_pos, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5077
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5078
  assert(min_split_pos <= optimal_split_pos && optimal_split_pos <= max_split_pos, "out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5079
  assert(optimal_split_pos <= it->to(),  "cannot split after end of interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5080
  assert(optimal_split_pos > it->from(), "cannot split at start of interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5081
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5082
  if (optimal_split_pos == it->to() && it->next_usage(mustHaveRegister, min_split_pos) == max_jint) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5083
    // the split position would be just before the end of the interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5084
    // -> no split at all necessary
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5085
    TRACE_LINEAR_SCAN(4, tty->print_cr("      no split necessary because optimal split position is at end of interval"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5086
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5087
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5088
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5089
  // must calculate this before the actual split is performed and before split position is moved to odd op_id
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5090
  bool move_necessary = !allocator()->is_block_begin(optimal_split_pos) && !it->has_hole_between(optimal_split_pos - 1, optimal_split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5091
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5092
  if (!allocator()->is_block_begin(optimal_split_pos)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5093
    // move position before actual instruction (odd op_id)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5094
    optimal_split_pos = (optimal_split_pos - 1) | 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5095
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5096
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5097
  TRACE_LINEAR_SCAN(4, tty->print_cr("      splitting at position %d", optimal_split_pos));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5098
  assert(allocator()->is_block_begin(optimal_split_pos) || (optimal_split_pos % 2 == 1), "split pos must be odd when not on block boundary");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5099
  assert(!allocator()->is_block_begin(optimal_split_pos) || (optimal_split_pos % 2 == 0), "split pos must be even on block boundary");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5100
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5101
  Interval* split_part = it->split(optimal_split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5102
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5103
  allocator()->append_interval(split_part);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5104
  allocator()->copy_register_flags(it, split_part);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5105
  split_part->set_insert_move_when_activated(move_necessary);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5106
  append_to_unhandled(unhandled_first_addr(anyKind), split_part);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5107
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5108
  TRACE_LINEAR_SCAN(2, tty->print_cr("      split interval in two parts (insert_move_when_activated: %d)", move_necessary));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5109
  TRACE_LINEAR_SCAN(2, tty->print   ("      "); it->print());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5110
  TRACE_LINEAR_SCAN(2, tty->print   ("      "); split_part->print());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5111
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5112
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5113
/*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5114
  split an interval at the optimal position between min_split_pos and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5115
  max_split_pos in two parts:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5116
  1) the left part has already a location assigned
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5117
  2) the right part is always on the stack and therefore ignored in further processing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5118
*/
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5119
void LinearScanWalker::split_for_spilling(Interval* it) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5120
  // calculate allowed range of splitting position
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5121
  int max_split_pos = current_position();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5122
  int min_split_pos = MAX2(it->previous_usage(shouldHaveRegister, max_split_pos) + 1, it->from());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5123
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5124
  TRACE_LINEAR_SCAN(2, tty->print   ("----- splitting and spilling interval: "); it->print());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5125
  TRACE_LINEAR_SCAN(2, tty->print_cr("      between %d and %d", min_split_pos, max_split_pos));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5126
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5127
  assert(it->state() == activeState,     "why spill interval that is not active?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5128
  assert(it->from() <= min_split_pos,    "cannot split before start of interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5129
  assert(min_split_pos <= max_split_pos, "invalid order");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5130
  assert(max_split_pos < it->to(),       "cannot split at end end of interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5131
  assert(current_position() < it->to(),  "interval must not end before current position");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5132
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5133
  if (min_split_pos == it->from()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5134
    // the whole interval is never used, so spill it entirely to memory
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5135
    TRACE_LINEAR_SCAN(2, tty->print_cr("      spilling entire interval because split pos is at beginning of interval"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5136
    assert(it->first_usage(shouldHaveRegister) > current_position(), "interval must not have use position before current_position");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5137
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5138
    allocator()->assign_spill_slot(it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5139
    allocator()->change_spill_state(it, min_split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5140
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5141
    // Also kick parent intervals out of register to memory when they have no use
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5142
    // position. This avoids short interval in register surrounded by intervals in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5143
    // memory -> avoid useless moves from memory to register and back
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5144
    Interval* parent = it;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5145
    while (parent != NULL && parent->is_split_child()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5146
      parent = parent->split_child_before_op_id(parent->from());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5147
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5148
      if (parent->assigned_reg() < LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5149
        if (parent->first_usage(shouldHaveRegister) == max_jint) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5150
          // parent is never used, so kick it out of its assigned register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5151
          TRACE_LINEAR_SCAN(4, tty->print_cr("      kicking out interval %d out of its register because it is never used", parent->reg_num()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5152
          allocator()->assign_spill_slot(parent);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5153
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5154
          // do not go further back because the register is actually used by the interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5155
          parent = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5156
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5157
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5158
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5159
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5160
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5161
    // search optimal split pos, split interval and spill only the right hand part
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5162
    int optimal_split_pos = find_optimal_split_pos(it, min_split_pos, max_split_pos, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5163
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5164
    assert(min_split_pos <= optimal_split_pos && optimal_split_pos <= max_split_pos, "out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5165
    assert(optimal_split_pos < it->to(), "cannot split at end of interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5166
    assert(optimal_split_pos >= it->from(), "cannot split before start of interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5167
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5168
    if (!allocator()->is_block_begin(optimal_split_pos)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5169
      // move position before actual instruction (odd op_id)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5170
      optimal_split_pos = (optimal_split_pos - 1) | 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5171
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5172
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5173
    TRACE_LINEAR_SCAN(4, tty->print_cr("      splitting at position %d", optimal_split_pos));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5174
    assert(allocator()->is_block_begin(optimal_split_pos)  || (optimal_split_pos % 2 == 1), "split pos must be odd when not on block boundary");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5175
    assert(!allocator()->is_block_begin(optimal_split_pos) || (optimal_split_pos % 2 == 0), "split pos must be even on block boundary");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5176
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5177
    Interval* spilled_part = it->split(optimal_split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5178
    allocator()->append_interval(spilled_part);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5179
    allocator()->assign_spill_slot(spilled_part);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5180
    allocator()->change_spill_state(spilled_part, optimal_split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5181
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5182
    if (!allocator()->is_block_begin(optimal_split_pos)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5183
      TRACE_LINEAR_SCAN(4, tty->print_cr("      inserting move from interval %d to %d", it->reg_num(), spilled_part->reg_num()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5184
      insert_move(optimal_split_pos, it, spilled_part);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5185
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5186
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5187
    // the current_split_child is needed later when moves are inserted for reloading
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5188
    assert(spilled_part->current_split_child() == it, "overwriting wrong current_split_child");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5189
    spilled_part->make_current_split_child();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5190
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5191
    TRACE_LINEAR_SCAN(2, tty->print_cr("      split interval in two parts"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5192
    TRACE_LINEAR_SCAN(2, tty->print   ("      "); it->print());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5193
    TRACE_LINEAR_SCAN(2, tty->print   ("      "); spilled_part->print());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5194
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5195
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5196
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5197
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5198
void LinearScanWalker::split_stack_interval(Interval* it) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5199
  int min_split_pos = current_position() + 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5200
  int max_split_pos = MIN2(it->first_usage(shouldHaveRegister), it->to());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5201
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5202
  split_before_usage(it, min_split_pos, max_split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5203
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5204
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5205
void LinearScanWalker::split_when_partial_register_available(Interval* it, int register_available_until) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5206
  int min_split_pos = MAX2(it->previous_usage(shouldHaveRegister, register_available_until), it->from() + 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5207
  int max_split_pos = register_available_until;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5208
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5209
  split_before_usage(it, min_split_pos, max_split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5210
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5211
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5212
void LinearScanWalker::split_and_spill_interval(Interval* it) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5213
  assert(it->state() == activeState || it->state() == inactiveState, "other states not allowed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5214
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5215
  int current_pos = current_position();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5216
  if (it->state() == inactiveState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5217
    // the interval is currently inactive, so no spill slot is needed for now.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5218
    // when the split part is activated, the interval has a new chance to get a register,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5219
    // so in the best case no stack slot is necessary
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5220
    assert(it->has_hole_between(current_pos - 1, current_pos + 1), "interval can not be inactive otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5221
    split_before_usage(it, current_pos + 1, current_pos + 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5222
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5223
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5224
    // search the position where the interval must have a register and split
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5225
    // at the optimal position before.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5226
    // The new created part is added to the unhandled list and will get a register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5227
    // when it is activated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5228
    int min_split_pos = current_pos + 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5229
    int max_split_pos = MIN2(it->next_usage(mustHaveRegister, min_split_pos), it->to());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5230
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5231
    split_before_usage(it, min_split_pos, max_split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5232
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5233
    assert(it->next_usage(mustHaveRegister, current_pos) == max_jint, "the remaining part is spilled to stack and therefore has no register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5234
    split_for_spilling(it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5235
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5236
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5237
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5238
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5239
int LinearScanWalker::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
  5240
  int min_full_reg = any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5241
  int max_partial_reg = any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5242
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5243
  for (int i = _first_reg; i <= _last_reg; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5244
    if (i == ignore_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5245
      // this register must be ignored
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5246
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5247
    } else if (_use_pos[i] >= interval_to) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5248
      // this register is free for the full interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5249
      if (min_full_reg == any_reg || i == hint_reg || (_use_pos[i] < _use_pos[min_full_reg] && min_full_reg != hint_reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5250
        min_full_reg = i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5251
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5252
    } else if (_use_pos[i] > reg_needed_until) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5253
      // this register is at least free until reg_needed_until
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5254
      if (max_partial_reg == any_reg || i == hint_reg || (_use_pos[i] > _use_pos[max_partial_reg] && max_partial_reg != hint_reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5255
        max_partial_reg = i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5256
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5257
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5258
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5259
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5260
  if (min_full_reg != any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5261
    return min_full_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5262
  } else if (max_partial_reg != any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5263
    *need_split = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5264
    return max_partial_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5265
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5266
    return any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5267
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5268
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5269
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5270
int LinearScanWalker::find_free_double_reg(int reg_needed_until, int interval_to, int hint_reg, bool* need_split) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5271
  assert((_last_reg - _first_reg + 1) % 2 == 0, "adjust algorithm");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5272
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5273
  int min_full_reg = any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5274
  int max_partial_reg = any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5275
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5276
  for (int i = _first_reg; i < _last_reg; i+=2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5277
    if (_use_pos[i] >= interval_to && _use_pos[i + 1] >= interval_to) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5278
      // this register is free for the full interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5279
      if (min_full_reg == any_reg || i == hint_reg || (_use_pos[i] < _use_pos[min_full_reg] && min_full_reg != hint_reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5280
        min_full_reg = i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5281
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5282
    } else if (_use_pos[i] > reg_needed_until && _use_pos[i + 1] > reg_needed_until) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5283
      // this register is at least free until reg_needed_until
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5284
      if (max_partial_reg == any_reg || i == hint_reg || (_use_pos[i] > _use_pos[max_partial_reg] && max_partial_reg != hint_reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5285
        max_partial_reg = i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5286
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5287
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5288
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5289
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5290
  if (min_full_reg != any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5291
    return min_full_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5292
  } else if (max_partial_reg != any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5293
    *need_split = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5294
    return max_partial_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5295
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5296
    return any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5297
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5298
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5299
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5300
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5301
bool LinearScanWalker::alloc_free_reg(Interval* cur) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5302
  TRACE_LINEAR_SCAN(2, tty->print("trying to find free register for "); cur->print());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5303
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5304
  init_use_lists(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5305
  free_exclude_active_fixed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5306
  free_exclude_active_any();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5307
  free_collect_inactive_fixed(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5308
  free_collect_inactive_any(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5309
//  free_collect_unhandled(fixedKind, cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5310
  assert(unhandled_first(fixedKind) == Interval::end(), "must not have unhandled fixed intervals because all fixed intervals have a use at position 0");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5311
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5312
  // _use_pos contains the start of the next interval that has this register assigned
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5313
  // (either as a fixed register or a normal allocated register in the past)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5314
  // only intervals overlapping with cur are processed, non-overlapping invervals can be ignored safely
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5315
  TRACE_LINEAR_SCAN(4, tty->print_cr("      state of registers:"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5316
  TRACE_LINEAR_SCAN(4, for (int i = _first_reg; i <= _last_reg; i++) tty->print_cr("      reg %d: use_pos: %d", i, _use_pos[i]));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5317
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5318
  int hint_reg, hint_regHi;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5319
  Interval* register_hint = cur->register_hint();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5320
  if (register_hint != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5321
    hint_reg = register_hint->assigned_reg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5322
    hint_regHi = register_hint->assigned_regHi();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5323
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5324
    if (allocator()->is_precolored_cpu_interval(register_hint)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5325
      assert(hint_reg != any_reg && hint_regHi == any_reg, "must be for fixed intervals");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5326
      hint_regHi = hint_reg + 1;  // connect e.g. eax-edx
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5327
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5328
    TRACE_LINEAR_SCAN(4, tty->print("      hint registers %d, %d from interval ", hint_reg, hint_regHi); register_hint->print());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5329
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5330
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5331
    hint_reg = any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5332
    hint_regHi = any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5333
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5334
  assert(hint_reg == any_reg || hint_reg != hint_regHi, "hint reg and regHi equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5335
  assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned to interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5336
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5337
  // the register must be free at least until this position
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5338
  int reg_needed_until = cur->from() + 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5339
  int interval_to = cur->to();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5340
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5341
  bool need_split = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5342
  int split_pos = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5343
  int reg = any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5344
  int regHi = any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5345
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5346
  if (_adjacent_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5347
    reg = find_free_double_reg(reg_needed_until, interval_to, hint_reg, &need_split);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5348
    regHi = reg + 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5349
    if (reg == any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5350
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5351
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5352
    split_pos = MIN2(_use_pos[reg], _use_pos[regHi]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5353
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5354
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5355
    reg = find_free_reg(reg_needed_until, interval_to, hint_reg, any_reg, &need_split);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5356
    if (reg == any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5357
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5358
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5359
    split_pos = _use_pos[reg];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5360
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5361
    if (_num_phys_regs == 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5362
      regHi = find_free_reg(reg_needed_until, interval_to, hint_regHi, reg, &need_split);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5363
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5364
      if (_use_pos[reg] < interval_to && regHi == any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5365
        // do not split interval if only one register can be assigned until the split pos
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5366
        // (when one register is found for the whole interval, split&spill is only
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5367
        // performed for the hi register)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5368
        return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5369
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5370
      } else if (regHi != any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5371
        split_pos = MIN2(split_pos, _use_pos[regHi]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5372
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5373
        // sort register numbers to prevent e.g. a move from eax,ebx to ebx,eax
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5374
        if (reg > regHi) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5375
          int temp = reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5376
          reg = regHi;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5377
          regHi = temp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5378
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5379
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5380
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5381
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5382
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5383
  cur->assign_reg(reg, regHi);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5384
  TRACE_LINEAR_SCAN(2, tty->print_cr("selected register %d, %d", reg, regHi));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5385
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5386
  assert(split_pos > 0, "invalid split_pos");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5387
  if (need_split) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5388
    // register not available for full interval, so split it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5389
    split_when_partial_register_available(cur, split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5390
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5391
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5392
  // only return true if interval is completely assigned
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5393
  return _num_phys_regs == 1 || regHi != any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5394
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5395
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5396
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5397
int LinearScanWalker::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
  5398
  int max_reg = any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5399
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5400
  for (int i = _first_reg; i <= _last_reg; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5401
    if (i == ignore_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5402
      // this register must be ignored
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5403
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5404
    } else if (_use_pos[i] > reg_needed_until) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5405
      if (max_reg == any_reg || i == hint_reg || (_use_pos[i] > _use_pos[max_reg] && max_reg != hint_reg)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5406
        max_reg = i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5407
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5408
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5409
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5410
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5411
  if (max_reg != any_reg && _block_pos[max_reg] <= interval_to) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5412
    *need_split = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5413
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5414
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5415
  return max_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5416
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5417
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5418
int LinearScanWalker::find_locked_double_reg(int reg_needed_until, int interval_to, int hint_reg, bool* need_split) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5419
  assert((_last_reg - _first_reg + 1) % 2 == 0, "adjust algorithm");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5420
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5421
  int max_reg = any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5422
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5423
  for (int i = _first_reg; i < _last_reg; i+=2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5424
    if (_use_pos[i] > reg_needed_until && _use_pos[i + 1] > reg_needed_until) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5425
      if (max_reg == any_reg || _use_pos[i] > _use_pos[max_reg]) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5426
        max_reg = i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5427
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5428
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5429
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5430
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5431
  if (_block_pos[max_reg] <= interval_to || _block_pos[max_reg + 1] <= interval_to) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5432
    *need_split = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5433
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5434
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5435
  return max_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5436
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5437
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5438
void LinearScanWalker::split_and_spill_intersecting_intervals(int reg, int regHi) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5439
  assert(reg != any_reg, "no register assigned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5440
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5441
  for (int i = 0; i < _spill_intervals[reg]->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5442
    Interval* it = _spill_intervals[reg]->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5443
    remove_from_list(it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5444
    split_and_spill_interval(it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5445
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5446
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5447
  if (regHi != any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5448
    IntervalList* processed = _spill_intervals[reg];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5449
    for (int i = 0; i < _spill_intervals[regHi]->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5450
      Interval* it = _spill_intervals[regHi]->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5451
      if (processed->index_of(it) == -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5452
        remove_from_list(it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5453
        split_and_spill_interval(it);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5454
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5455
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5456
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5457
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5458
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5459
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5460
// Split an Interval and spill it to memory so that cur can be placed in a register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5461
void LinearScanWalker::alloc_locked_reg(Interval* cur) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5462
  TRACE_LINEAR_SCAN(2, tty->print("need to split and spill to get register for "); cur->print());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5463
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5464
  // collect current usage of registers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5465
  init_use_lists(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5466
  spill_exclude_active_fixed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5467
//  spill_block_unhandled_fixed(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5468
  assert(unhandled_first(fixedKind) == Interval::end(), "must not have unhandled fixed intervals because all fixed intervals have a use at position 0");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5469
  spill_block_inactive_fixed(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5470
  spill_collect_active_any();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5471
  spill_collect_inactive_any(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5472
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5473
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5474
  if (TraceLinearScanLevel >= 4) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5475
    tty->print_cr("      state of registers:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5476
    for (int i = _first_reg; i <= _last_reg; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5477
      tty->print("      reg %d: use_pos: %d, block_pos: %d, intervals: ", i, _use_pos[i], _block_pos[i]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5478
      for (int j = 0; j < _spill_intervals[i]->length(); j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5479
        tty->print("%d ", _spill_intervals[i]->at(j)->reg_num());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5480
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5481
      tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5482
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5483
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5484
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5485
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5486
  // the register must be free at least until this position
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5487
  int reg_needed_until = MIN2(cur->first_usage(mustHaveRegister), cur->from() + 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5488
  int interval_to = cur->to();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5489
  assert (reg_needed_until > 0 && reg_needed_until < max_jint, "interval has no use");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5490
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5491
  int split_pos = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5492
  int use_pos = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5493
  bool need_split = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5494
  int reg, regHi;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5495
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5496
  if (_adjacent_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5497
    reg = find_locked_double_reg(reg_needed_until, interval_to, any_reg, &need_split);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5498
    regHi = reg + 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5499
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5500
    if (reg != any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5501
      use_pos = MIN2(_use_pos[reg], _use_pos[regHi]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5502
      split_pos = MIN2(_block_pos[reg], _block_pos[regHi]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5503
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5504
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5505
    reg = find_locked_reg(reg_needed_until, interval_to, any_reg, cur->assigned_reg(), &need_split);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5506
    regHi = any_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5507
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5508
    if (reg != any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5509
      use_pos = _use_pos[reg];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5510
      split_pos = _block_pos[reg];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5511
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5512
      if (_num_phys_regs == 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5513
        if (cur->assigned_reg() != any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5514
          regHi = reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5515
          reg = cur->assigned_reg();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5516
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5517
          regHi = find_locked_reg(reg_needed_until, interval_to, any_reg, reg, &need_split);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5518
          if (regHi != any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5519
            use_pos = MIN2(use_pos, _use_pos[regHi]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5520
            split_pos = MIN2(split_pos, _block_pos[regHi]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5521
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5522
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5523
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5524
        if (regHi != any_reg && reg > regHi) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5525
          // sort register numbers to prevent e.g. a move from eax,ebx to ebx,eax
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5526
          int temp = reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5527
          reg = regHi;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5528
          regHi = temp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5529
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5530
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5531
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5532
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5533
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5534
  if (reg == any_reg || (_num_phys_regs == 2 && regHi == any_reg) || use_pos <= cur->first_usage(mustHaveRegister)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5535
    // the first use of cur is later than the spilling position -> spill cur
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5536
    TRACE_LINEAR_SCAN(4, tty->print_cr("able to spill current interval. first_usage(register): %d, use_pos: %d", cur->first_usage(mustHaveRegister), use_pos));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5537
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5538
    if (cur->first_usage(mustHaveRegister) <= cur->from() + 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5539
      assert(false, "cannot spill interval that is used in first instruction (possible reason: no register found)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5540
      // assign a reasonable register and do a bailout in product mode to avoid errors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5541
      allocator()->assign_spill_slot(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5542
      BAILOUT("LinearScan: no register found");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5543
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5544
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5545
    split_and_spill_interval(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5546
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5547
    TRACE_LINEAR_SCAN(4, tty->print_cr("decided to use register %d, %d", reg, regHi));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5548
    assert(reg != any_reg && (_num_phys_regs == 1 || regHi != any_reg), "no register found");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5549
    assert(split_pos > 0, "invalid split_pos");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5550
    assert(need_split == false || split_pos > cur->from(), "splitting interval at from");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5551
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5552
    cur->assign_reg(reg, regHi);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5553
    if (need_split) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5554
      // register not available for full interval, so split it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5555
      split_when_partial_register_available(cur, split_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5556
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5557
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5558
    // perform splitting and spilling for all affected intervalls
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5559
    split_and_spill_intersecting_intervals(reg, regHi);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5560
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5561
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5562
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5563
bool LinearScanWalker::no_allocation_possible(Interval* cur) {
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
  5564
#ifdef X86
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5565
  // fast calculation of intervals that can never get a register because the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5566
  // the next instruction is a call that blocks all registers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5567
  // Note: this does not work if callee-saved registers are available (e.g. on Sparc)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5568
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5569
  // check if this interval is the result of a split operation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5570
  // (an interval got a register until this position)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5571
  int pos = cur->from();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5572
  if ((pos & 1) == 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5573
    // the current instruction is a call that blocks all registers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5574
    if (pos < allocator()->max_lir_op_id() && allocator()->has_call(pos + 1)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5575
      TRACE_LINEAR_SCAN(4, tty->print_cr("      free register cannot be available because all registers blocked by following call"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5576
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5577
      // safety check that there is really no register available
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5578
      assert(alloc_free_reg(cur) == false, "found a register for this interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5579
      return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5580
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5581
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5582
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5583
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5584
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5585
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5586
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5587
void LinearScanWalker::init_vars_for_alloc(Interval* cur) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5588
  BasicType type = cur->type();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5589
  _num_phys_regs = LinearScan::num_physical_regs(type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5590
  _adjacent_regs = LinearScan::requires_adjacent_regs(type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5591
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5592
  if (pd_init_regs_for_alloc(cur)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5593
    // the appropriate register range was selected.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5594
  } else if (type == T_FLOAT || type == T_DOUBLE) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5595
    _first_reg = pd_first_fpu_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5596
    _last_reg = pd_last_fpu_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5597
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5598
    _first_reg = pd_first_cpu_reg;
7427
d7b79a367474 6985015: C1 needs to support compressed oops
iveresov
parents: 7397
diff changeset
  5599
    _last_reg = FrameMap::last_cpu_reg();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5600
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5601
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5602
  assert(0 <= _first_reg && _first_reg < LinearScan::nof_regs, "out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5603
  assert(0 <= _last_reg && _last_reg < LinearScan::nof_regs, "out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5604
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5605
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5606
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5607
bool LinearScanWalker::is_move(LIR_Op* op, Interval* from, Interval* to) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5608
  if (op->code() != lir_move) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5609
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5610
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5611
  assert(op->as_Op1() != NULL, "move must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5612
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5613
  LIR_Opr in = ((LIR_Op1*)op)->in_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5614
  LIR_Opr res = ((LIR_Op1*)op)->result_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5615
  return in->is_virtual() && res->is_virtual() && in->vreg_number() == from->reg_num() && res->vreg_number() == to->reg_num();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5616
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5617
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5618
// optimization (especially for phi functions of nested loops):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5619
// assign same spill slot to non-intersecting intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5620
void LinearScanWalker::combine_spilled_intervals(Interval* cur) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5621
  if (cur->is_split_child()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5622
    // optimization is only suitable for split parents
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5623
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5624
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5625
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5626
  Interval* register_hint = cur->register_hint(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5627
  if (register_hint == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5628
    // cur is not the target of a move, otherwise register_hint would be set
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5629
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5630
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5631
  assert(register_hint->is_split_parent(), "register hint must be split parent");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5632
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5633
  if (cur->spill_state() != noOptimization || register_hint->spill_state() != noOptimization) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5634
    // combining the stack slots for intervals where spill move optimization is applied
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5635
    // is not benefitial and would cause problems
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5636
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5637
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5638
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5639
  int begin_pos = cur->from();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5640
  int end_pos = cur->to();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5641
  if (end_pos > allocator()->max_lir_op_id() || (begin_pos & 1) != 0 || (end_pos & 1) != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5642
    // safety check that lir_op_with_id is allowed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5643
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5644
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5645
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5646
  if (!is_move(allocator()->lir_op_with_id(begin_pos), register_hint, cur) || !is_move(allocator()->lir_op_with_id(end_pos), cur, register_hint)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5647
    // cur and register_hint are not connected with two moves
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5648
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5649
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5650
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5651
  Interval* begin_hint = register_hint->split_child_at_op_id(begin_pos, LIR_OpVisitState::inputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5652
  Interval* end_hint = register_hint->split_child_at_op_id(end_pos, LIR_OpVisitState::outputMode);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5653
  if (begin_hint == end_hint || begin_hint->to() != begin_pos || end_hint->from() != end_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5654
    // register_hint must be split, otherwise the re-writing of use positions does not work
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5655
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5656
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5657
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5658
  assert(begin_hint->assigned_reg() != any_reg, "must have register assigned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5659
  assert(end_hint->assigned_reg() == any_reg, "must not have register assigned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5660
  assert(cur->first_usage(mustHaveRegister) == begin_pos, "must have use position at begin of interval because of move");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5661
  assert(end_hint->first_usage(mustHaveRegister) == end_pos, "must have use position at begin of interval because of move");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5662
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5663
  if (begin_hint->assigned_reg() < LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5664
    // register_hint is not spilled at begin_pos, so it would not be benefitial to immediately spill cur
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5665
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5666
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5667
  assert(register_hint->canonical_spill_slot() != -1, "must be set when part of interval was spilled");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5668
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5669
  // modify intervals such that cur gets the same stack slot as register_hint
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5670
  // delete use positions to prevent the intervals to get a register at beginning
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5671
  cur->set_canonical_spill_slot(register_hint->canonical_spill_slot());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5672
  cur->remove_first_use_pos();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5673
  end_hint->remove_first_use_pos();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5674
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5675
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5676
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5677
// allocate a physical register or memory location to an interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5678
bool LinearScanWalker::activate_current() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5679
  Interval* cur = current();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5680
  bool result = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5681
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5682
  TRACE_LINEAR_SCAN(2, tty->print   ("+++++ activating interval "); cur->print());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5683
  TRACE_LINEAR_SCAN(4, tty->print_cr("      split_parent: %d, insert_move_when_activated: %d", cur->split_parent()->reg_num(), cur->insert_move_when_activated()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5684
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5685
  if (cur->assigned_reg() >= LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5686
    // activating an interval that has a stack slot assigned -> split it at first use position
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5687
    // used for method parameters
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5688
    TRACE_LINEAR_SCAN(4, tty->print_cr("      interval has spill slot assigned (method parameter) -> split it before first use"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5689
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5690
    split_stack_interval(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5691
    result = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5692
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5693
  } else if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::must_start_in_memory)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5694
    // activating an interval that must start in a stack slot, but may get a register later
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5695
    // used for lir_roundfp: rounding is done by store to stack and reload later
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5696
    TRACE_LINEAR_SCAN(4, tty->print_cr("      interval must start in stack slot -> split it before first use"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5697
    assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5698
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5699
    allocator()->assign_spill_slot(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5700
    split_stack_interval(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5701
    result = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5702
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5703
  } else if (cur->assigned_reg() == any_reg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5704
    // interval has not assigned register -> normal allocation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5705
    // (this is the normal case for most intervals)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5706
    TRACE_LINEAR_SCAN(4, tty->print_cr("      normal allocation of register"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5707
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5708
    // assign same spill slot to non-intersecting intervals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5709
    combine_spilled_intervals(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5710
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5711
    init_vars_for_alloc(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5712
    if (no_allocation_possible(cur) || !alloc_free_reg(cur)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5713
      // no empty register available.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5714
      // split and spill another interval so that this interval gets a register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5715
      alloc_locked_reg(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5716
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5717
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5718
    // spilled intervals need not be move to active-list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5719
    if (cur->assigned_reg() >= LinearScan::nof_regs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5720
      result = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5721
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5722
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5723
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5724
  // load spilled values that become active from stack slot to register
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5725
  if (cur->insert_move_when_activated()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5726
    assert(cur->is_split_child(), "must be");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5727
    assert(cur->current_split_child() != NULL, "must be");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5728
    assert(cur->current_split_child()->reg_num() != cur->reg_num(), "cannot insert move between same interval");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5729
    TRACE_LINEAR_SCAN(4, tty->print_cr("Inserting move from interval %d to %d because insert_move_when_activated is set", cur->current_split_child()->reg_num(), cur->reg_num()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5730
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5731
    insert_move(cur->from(), cur->current_split_child(), cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5732
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5733
  cur->make_current_split_child();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5734
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5735
  return result; // true = interval is moved to active list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5736
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5737
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5738
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5739
// Implementation of EdgeMoveOptimizer
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5740
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5741
EdgeMoveOptimizer::EdgeMoveOptimizer() :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5742
  _edge_instructions(4),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5743
  _edge_instructions_idx(4)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5744
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5745
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5746
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5747
void EdgeMoveOptimizer::optimize(BlockList* code) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5748
  EdgeMoveOptimizer optimizer = EdgeMoveOptimizer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5749
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5750
  // ignore the first block in the list (index 0 is not processed)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5751
  for (int i = code->length() - 1; i >= 1; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5752
    BlockBegin* block = code->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5753
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5754
    if (block->number_of_preds() > 1 && !block->is_set(BlockBegin::exception_entry_flag)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5755
      optimizer.optimize_moves_at_block_end(block);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5756
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5757
    if (block->number_of_sux() == 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5758
      optimizer.optimize_moves_at_block_begin(block);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5759
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5760
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5761
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5762
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5763
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5764
// clear all internal data structures
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5765
void EdgeMoveOptimizer::init_instructions() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5766
  _edge_instructions.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5767
  _edge_instructions_idx.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5768
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5769
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5770
// append a lir-instruction-list and the index of the current operation in to the list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5771
void EdgeMoveOptimizer::append_instructions(LIR_OpList* instructions, int instructions_idx) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5772
  _edge_instructions.append(instructions);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5773
  _edge_instructions_idx.append(instructions_idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5774
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5775
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5776
// return the current operation of the given edge (predecessor or successor)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5777
LIR_Op* EdgeMoveOptimizer::instruction_at(int edge) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5778
  LIR_OpList* instructions = _edge_instructions.at(edge);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5779
  int idx = _edge_instructions_idx.at(edge);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5780
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5781
  if (idx < instructions->length()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5782
    return instructions->at(idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5783
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5784
    return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5785
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5786
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5787
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5788
// removes the current operation of the given edge (predecessor or successor)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5789
void EdgeMoveOptimizer::remove_cur_instruction(int edge, bool decrement_index) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5790
  LIR_OpList* instructions = _edge_instructions.at(edge);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5791
  int idx = _edge_instructions_idx.at(edge);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5792
  instructions->remove_at(idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5793
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5794
  if (decrement_index) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5795
    _edge_instructions_idx.at_put(edge, idx - 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5796
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5797
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5798
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5799
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5800
bool EdgeMoveOptimizer::operations_different(LIR_Op* op1, LIR_Op* op2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5801
  if (op1 == NULL || op2 == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5802
    // at least one block is already empty -> no optimization possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5803
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5804
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5805
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5806
  if (op1->code() == lir_move && op2->code() == lir_move) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5807
    assert(op1->as_Op1() != NULL, "move must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5808
    assert(op2->as_Op1() != NULL, "move must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5809
    LIR_Op1* move1 = (LIR_Op1*)op1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5810
    LIR_Op1* move2 = (LIR_Op1*)op2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5811
    if (move1->info() == move2->info() && move1->in_opr() == move2->in_opr() && move1->result_opr() == move2->result_opr()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5812
      // these moves are exactly equal and can be optimized
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5813
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5814
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5815
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5816
  } else if (op1->code() == lir_fxch && op2->code() == lir_fxch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5817
    assert(op1->as_Op1() != NULL, "fxch must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5818
    assert(op2->as_Op1() != NULL, "fxch must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5819
    LIR_Op1* fxch1 = (LIR_Op1*)op1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5820
    LIR_Op1* fxch2 = (LIR_Op1*)op2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5821
    if (fxch1->in_opr()->as_jint() == fxch2->in_opr()->as_jint()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5822
      // equal FPU stack operations can be optimized
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5823
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5824
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5825
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5826
  } else if (op1->code() == lir_fpop_raw && op2->code() == lir_fpop_raw) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5827
    // equal FPU stack operations can be optimized
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5828
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5829
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5830
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5831
  // no optimization possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5832
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5833
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5834
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5835
void EdgeMoveOptimizer::optimize_moves_at_block_end(BlockBegin* block) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5836
  TRACE_LINEAR_SCAN(4, tty->print_cr("optimizing moves at end of block B%d", block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5837
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5838
  if (block->is_predecessor(block)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5839
    // currently we can't handle this correctly.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5840
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5841
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5842
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5843
  init_instructions();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5844
  int num_preds = block->number_of_preds();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5845
  assert(num_preds > 1, "do not call otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5846
  assert(!block->is_set(BlockBegin::exception_entry_flag), "exception handlers not allowed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5847
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5848
  // setup a list with the lir-instructions of all predecessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5849
  int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5850
  for (i = 0; i < num_preds; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5851
    BlockBegin* pred = block->pred_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5852
    LIR_OpList* pred_instructions = pred->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5853
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5854
    if (pred->number_of_sux() != 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5855
      // this can happen with switch-statements where multiple edges are between
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5856
      // the same blocks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5857
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5858
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5859
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5860
    assert(pred->number_of_sux() == 1, "can handle only one successor");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5861
    assert(pred->sux_at(0) == block, "invalid control flow");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5862
    assert(pred_instructions->last()->code() == lir_branch, "block with successor must end with branch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5863
    assert(pred_instructions->last()->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5864
    assert(pred_instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block must end with unconditional branch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5865
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5866
    if (pred_instructions->last()->info() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5867
      // can not optimize instructions when debug info is needed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5868
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5869
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5870
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5871
    // ignore the unconditional branch at the end of the block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5872
    append_instructions(pred_instructions, pred_instructions->length() - 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5873
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5874
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5875
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5876
  // process lir-instructions while all predecessors end with the same instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5877
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5878
    LIR_Op* op = instruction_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5879
    for (i = 1; i < num_preds; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5880
      if (operations_different(op, instruction_at(i))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5881
        // these instructions are different and cannot be optimized ->
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5882
        // no further optimization possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5883
        return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5884
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5885
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5886
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5887
    TRACE_LINEAR_SCAN(4, tty->print("found instruction that is equal in all %d predecessors: ", num_preds); op->print());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5888
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5889
    // insert the instruction at the beginning of the current block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5890
    block->lir()->insert_before(1, op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5891
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5892
    // delete the instruction at the end of all predecessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5893
    for (i = 0; i < num_preds; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5894
      remove_cur_instruction(i, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5895
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5896
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5897
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5898
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5899
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5900
void EdgeMoveOptimizer::optimize_moves_at_block_begin(BlockBegin* block) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5901
  TRACE_LINEAR_SCAN(4, tty->print_cr("optimization moves at begin of block B%d", block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5902
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5903
  init_instructions();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5904
  int num_sux = block->number_of_sux();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5905
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5906
  LIR_OpList* cur_instructions = block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5907
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5908
  assert(num_sux == 2, "method should not be called otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5909
  assert(cur_instructions->last()->code() == lir_branch, "block with successor must end with branch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5910
  assert(cur_instructions->last()->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5911
  assert(cur_instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block must end with unconditional branch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5912
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5913
  if (cur_instructions->last()->info() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5914
    // can no optimize instructions when debug info is needed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5915
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5916
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5917
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5918
  LIR_Op* branch = cur_instructions->at(cur_instructions->length() - 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5919
  if (branch->info() != NULL || (branch->code() != lir_branch && branch->code() != lir_cond_float_branch)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5920
    // not a valid case for optimization
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5921
    // currently, only blocks that end with two branches (conditional branch followed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5922
    // by unconditional branch) are optimized
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5923
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5924
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5925
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5926
  // now it is guaranteed that the block ends with two branch instructions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5927
  // the instructions are inserted at the end of the block before these two branches
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5928
  int insert_idx = cur_instructions->length() - 2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5929
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5930
  int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5931
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5932
  for (i = insert_idx - 1; i >= 0; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5933
    LIR_Op* op = cur_instructions->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5934
    if ((op->code() == lir_branch || op->code() == lir_cond_float_branch) && ((LIR_OpBranch*)op)->block() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5935
      assert(false, "block with two successors can have only two branch instructions");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5936
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5937
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5938
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5939
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5940
  // setup a list with the lir-instructions of all successors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5941
  for (i = 0; i < num_sux; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5942
    BlockBegin* sux = block->sux_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5943
    LIR_OpList* sux_instructions = sux->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5944
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5945
    assert(sux_instructions->at(0)->code() == lir_label, "block must start with label");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5946
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5947
    if (sux->number_of_preds() != 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5948
      // this can happen with switch-statements where multiple edges are between
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5949
      // the same blocks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5950
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5951
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5952
    assert(sux->pred_at(0) == block, "invalid control flow");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5953
    assert(!sux->is_set(BlockBegin::exception_entry_flag), "exception handlers not allowed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5954
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5955
    // ignore the label at the beginning of the block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5956
    append_instructions(sux_instructions, 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5957
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5958
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5959
  // process lir-instructions while all successors begin with the same instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5960
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5961
    LIR_Op* op = instruction_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5962
    for (i = 1; i < num_sux; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5963
      if (operations_different(op, instruction_at(i))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5964
        // these instructions are different and cannot be optimized ->
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5965
        // no further optimization possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5966
        return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5967
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5968
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5969
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5970
    TRACE_LINEAR_SCAN(4, tty->print("----- found instruction that is equal in all %d successors: ", num_sux); op->print());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5971
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5972
    // insert instruction at end of current block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5973
    block->lir()->insert_before(insert_idx, op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5974
    insert_idx++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5975
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5976
    // delete the instructions at the beginning of all successors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5977
    for (i = 0; i < num_sux; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5978
      remove_cur_instruction(i, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5979
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5980
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5981
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5982
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5983
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5984
// Implementation of ControlFlowOptimizer
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5985
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5986
ControlFlowOptimizer::ControlFlowOptimizer() :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5987
  _original_preds(4)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5988
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5989
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5990
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5991
void ControlFlowOptimizer::optimize(BlockList* code) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5992
  ControlFlowOptimizer optimizer = ControlFlowOptimizer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5993
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5994
  // push the OSR entry block to the end so that we're not jumping over it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5995
  BlockBegin* osr_entry = code->at(0)->end()->as_Base()->osr_entry();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5996
  if (osr_entry) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5997
    int index = osr_entry->linear_scan_number();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5998
    assert(code->at(index) == osr_entry, "wrong index");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5999
    code->remove_at(index);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6000
    code->append(osr_entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6001
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6002
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6003
  optimizer.reorder_short_loops(code);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6004
  optimizer.delete_empty_blocks(code);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6005
  optimizer.delete_unnecessary_jumps(code);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6006
  optimizer.delete_jumps_to_return(code);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6007
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6008
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6009
void ControlFlowOptimizer::reorder_short_loop(BlockList* code, BlockBegin* header_block, int header_idx) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6010
  int i = header_idx + 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6011
  int max_end = MIN2(header_idx + ShortLoopSize, code->length());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6012
  while (i < max_end && code->at(i)->loop_depth() >= header_block->loop_depth()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6013
    i++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6014
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6015
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6016
  if (i == code->length() || code->at(i)->loop_depth() < header_block->loop_depth()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6017
    int end_idx = i - 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6018
    BlockBegin* end_block = code->at(end_idx);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6019
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6020
    if (end_block->number_of_sux() == 1 && end_block->sux_at(0) == header_block) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6021
      // short loop from header_idx to end_idx found -> reorder blocks such that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6022
      // the header_block is the last block instead of the first block of the loop
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6023
      TRACE_LINEAR_SCAN(1, tty->print_cr("Reordering short loop: length %d, header B%d, end B%d",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6024
                                         end_idx - header_idx + 1,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6025
                                         header_block->block_id(), end_block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6026
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6027
      for (int j = header_idx; j < end_idx; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6028
        code->at_put(j, code->at(j + 1));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6029
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6030
      code->at_put(end_idx, header_block);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6031
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6032
      // correct the flags so that any loop alignment occurs in the right place.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6033
      assert(code->at(end_idx)->is_set(BlockBegin::backward_branch_target_flag), "must be backward branch target");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6034
      code->at(end_idx)->clear(BlockBegin::backward_branch_target_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6035
      code->at(header_idx)->set(BlockBegin::backward_branch_target_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6036
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6037
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6038
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6039
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6040
void ControlFlowOptimizer::reorder_short_loops(BlockList* code) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6041
  for (int i = code->length() - 1; i >= 0; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6042
    BlockBegin* block = code->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6043
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6044
    if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6045
      reorder_short_loop(code, block, i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6046
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6047
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6048
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6049
  DEBUG_ONLY(verify(code));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6050
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6051
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6052
// only blocks with exactly one successor can be deleted. Such blocks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6053
// must always end with an unconditional branch to this successor
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6054
bool ControlFlowOptimizer::can_delete_block(BlockBegin* block) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6055
  if (block->number_of_sux() != 1 || block->number_of_exception_handlers() != 0 || block->is_entry_block()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6056
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6057
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6058
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6059
  LIR_OpList* instructions = block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6060
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6061
  assert(instructions->length() >= 2, "block must have label and branch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6062
  assert(instructions->at(0)->code() == lir_label, "first instruction must always be a label");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6063
  assert(instructions->last()->as_OpBranch() != NULL, "last instrcution must always be a branch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6064
  assert(instructions->last()->as_OpBranch()->cond() == lir_cond_always, "branch must be unconditional");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6065
  assert(instructions->last()->as_OpBranch()->block() == block->sux_at(0), "branch target must be the successor");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6066
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6067
  // block must have exactly one successor
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6068
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6069
  if (instructions->length() == 2 && instructions->last()->info() == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6070
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6071
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6072
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6073
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6074
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6075
// substitute branch targets in all branch-instructions of this blocks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6076
void ControlFlowOptimizer::substitute_branch_target(BlockBegin* block, BlockBegin* target_from, BlockBegin* target_to) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6077
  TRACE_LINEAR_SCAN(3, tty->print_cr("Deleting empty block: substituting from B%d to B%d inside B%d", target_from->block_id(), target_to->block_id(), block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6078
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6079
  LIR_OpList* instructions = block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6080
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6081
  assert(instructions->at(0)->code() == lir_label, "first instruction must always be a label");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6082
  for (int i = instructions->length() - 1; i >= 1; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6083
    LIR_Op* op = instructions->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6084
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6085
    if (op->code() == lir_branch || op->code() == lir_cond_float_branch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6086
      assert(op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6087
      LIR_OpBranch* branch = (LIR_OpBranch*)op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6088
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6089
      if (branch->block() == target_from) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6090
        branch->change_block(target_to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6091
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6092
      if (branch->ublock() == target_from) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6093
        branch->change_ublock(target_to);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6094
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6095
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6096
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6097
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6098
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6099
void ControlFlowOptimizer::delete_empty_blocks(BlockList* code) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6100
  int old_pos = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6101
  int new_pos = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6102
  int num_blocks = code->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6103
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6104
  while (old_pos < num_blocks) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6105
    BlockBegin* block = code->at(old_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6106
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6107
    if (can_delete_block(block)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6108
      BlockBegin* new_target = block->sux_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6109
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6110
      // propagate backward branch target flag for correct code alignment
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6111
      if (block->is_set(BlockBegin::backward_branch_target_flag)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6112
        new_target->set(BlockBegin::backward_branch_target_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6113
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6114
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6115
      // collect a list with all predecessors that contains each predecessor only once
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6116
      // the predecessors of cur are changed during the substitution, so a copy of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6117
      // predecessor list is necessary
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6118
      int j;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6119
      _original_preds.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6120
      for (j = block->number_of_preds() - 1; j >= 0; j--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6121
        BlockBegin* pred = block->pred_at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6122
        if (_original_preds.index_of(pred) == -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6123
          _original_preds.append(pred);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6124
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6125
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6126
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6127
      for (j = _original_preds.length() - 1; j >= 0; j--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6128
        BlockBegin* pred = _original_preds.at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6129
        substitute_branch_target(pred, block, new_target);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6130
        pred->substitute_sux(block, new_target);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6131
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6132
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6133
      // adjust position of this block in the block list if blocks before
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6134
      // have been deleted
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6135
      if (new_pos != old_pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6136
        code->at_put(new_pos, code->at(old_pos));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6137
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6138
      new_pos++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6139
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6140
    old_pos++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6141
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6142
  code->truncate(new_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6143
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6144
  DEBUG_ONLY(verify(code));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6145
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6146
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6147
void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6148
  // skip the last block because there a branch is always necessary
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6149
  for (int i = code->length() - 2; i >= 0; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6150
    BlockBegin* block = code->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6151
    LIR_OpList* instructions = block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6152
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6153
    LIR_Op* last_op = instructions->last();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6154
    if (last_op->code() == lir_branch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6155
      assert(last_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6156
      LIR_OpBranch* last_branch = (LIR_OpBranch*)last_op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6157
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6158
      assert(last_branch->block() != NULL, "last branch must always have a block as target");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6159
      assert(last_branch->label() == last_branch->block()->label(), "must be equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6160
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6161
      if (last_branch->info() == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6162
        if (last_branch->block() == code->at(i + 1)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6163
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6164
          TRACE_LINEAR_SCAN(3, tty->print_cr("Deleting unconditional branch at end of block B%d", block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6165
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6166
          // delete last branch instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6167
          instructions->truncate(instructions->length() - 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6168
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6169
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6170
          LIR_Op* prev_op = instructions->at(instructions->length() - 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6171
          if (prev_op->code() == lir_branch || prev_op->code() == lir_cond_float_branch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6172
            assert(prev_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6173
            LIR_OpBranch* prev_branch = (LIR_OpBranch*)prev_op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6174
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  6175
            LIR_Op2* prev_cmp = NULL;
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  6177
            for(int j = instructions->length() - 3; j >= 0 && prev_cmp == NULL; j--) {
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  6178
              prev_op = instructions->at(j);
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  6179
              if(prev_op->code() == lir_cmp) {
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  6180
                assert(prev_op->as_Op2() != NULL, "branch must be of type LIR_Op2");
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  6181
                prev_cmp = (LIR_Op2*)prev_op;
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  6182
                assert(prev_branch->cond() == prev_cmp->condition(), "should be the same");
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  6183
              }
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  6184
            }
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  6185
            assert(prev_cmp != NULL, "should have found comp instruction for branch");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6186
            if (prev_branch->block() == code->at(i + 1) && prev_branch->info() == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6187
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6188
              TRACE_LINEAR_SCAN(3, tty->print_cr("Negating conditional branch and deleting unconditional branch at end of block B%d", block->block_id()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6189
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6190
              // eliminate a conditional branch to the immediate successor
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6191
              prev_branch->change_block(last_branch->block());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6192
              prev_branch->negate_cond();
6176
4d9030fe341f 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 5707
diff changeset
  6193
              prev_cmp->set_condition(prev_branch->cond());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6194
              instructions->truncate(instructions->length() - 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6195
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6196
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6197
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6198
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6199
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6200
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6201
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6202
  DEBUG_ONLY(verify(code));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6203
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6204
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6205
void ControlFlowOptimizer::delete_jumps_to_return(BlockList* code) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6206
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6207
  BitMap return_converted(BlockBegin::number_of_blocks());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6208
  return_converted.clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6209
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6210
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6211
  for (int i = code->length() - 1; i >= 0; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6212
    BlockBegin* block = code->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6213
    LIR_OpList* cur_instructions = block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6214
    LIR_Op*     cur_last_op = cur_instructions->last();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6215
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6216
    assert(cur_instructions->at(0)->code() == lir_label, "first instruction must always be a label");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6217
    if (cur_instructions->length() == 2 && cur_last_op->code() == lir_return) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6218
      // the block contains only a label and a return
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6219
      // if a predecessor ends with an unconditional jump to this block, then the jump
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6220
      // can be replaced with a return instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6221
      //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6222
      // Note: the original block with only a return statement cannot be deleted completely
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6223
      //       because the predecessors might have other (conditional) jumps to this block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6224
      //       -> this may lead to unnecesary return instructions in the final code
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6225
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6226
      assert(cur_last_op->info() == NULL, "return instructions do not have debug information");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6227
      assert(block->number_of_sux() == 0 ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6228
             (return_converted.at(block->block_id()) && block->number_of_sux() == 1),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6229
             "blocks that end with return must not have successors");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6230
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6231
      assert(cur_last_op->as_Op1() != NULL, "return must be LIR_Op1");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6232
      LIR_Opr return_opr = ((LIR_Op1*)cur_last_op)->in_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6233
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6234
      for (int j = block->number_of_preds() - 1; j >= 0; j--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6235
        BlockBegin* pred = block->pred_at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6236
        LIR_OpList* pred_instructions = pred->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6237
        LIR_Op*     pred_last_op = pred_instructions->last();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6238
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6239
        if (pred_last_op->code() == lir_branch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6240
          assert(pred_last_op->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6241
          LIR_OpBranch* pred_last_branch = (LIR_OpBranch*)pred_last_op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6242
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6243
          if (pred_last_branch->block() == block && pred_last_branch->cond() == lir_cond_always && pred_last_branch->info() == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6244
            // replace the jump to a return with a direct return
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6245
            // Note: currently the edge between the blocks is not deleted
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6246
            pred_instructions->at_put(pred_instructions->length() - 1, new LIR_Op1(lir_return, return_opr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6247
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6248
            return_converted.set_bit(pred->block_id());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6249
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6250
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6251
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6252
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6253
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6254
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6255
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6256
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6257
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6258
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6259
void ControlFlowOptimizer::verify(BlockList* code) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6260
  for (int i = 0; i < code->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6261
    BlockBegin* block = code->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6262
    LIR_OpList* instructions = block->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6263
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6264
    int j;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6265
    for (j = 0; j < instructions->length(); j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6266
      LIR_OpBranch* op_branch = instructions->at(j)->as_OpBranch();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6267
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6268
      if (op_branch != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6269
        assert(op_branch->block() == NULL || code->index_of(op_branch->block()) != -1, "branch target not valid");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6270
        assert(op_branch->ublock() == NULL || code->index_of(op_branch->ublock()) != -1, "branch target not valid");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6271
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6272
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6273
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6274
    for (j = 0; j < block->number_of_sux() - 1; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6275
      BlockBegin* sux = block->sux_at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6276
      assert(code->index_of(sux) != -1, "successor not valid");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6277
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6278
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6279
    for (j = 0; j < block->number_of_preds() - 1; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6280
      BlockBegin* pred = block->pred_at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6281
      assert(code->index_of(pred) != -1, "successor not valid");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6282
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6283
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6284
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6285
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6286
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6287
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6288
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6289
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6290
// Implementation of LinearStatistic
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6291
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6292
const char* LinearScanStatistic::counter_name(int counter_idx) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6293
  switch (counter_idx) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6294
    case counter_method:          return "compiled methods";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6295
    case counter_fpu_method:      return "methods using fpu";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6296
    case counter_loop_method:     return "methods with loops";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6297
    case counter_exception_method:return "methods with xhandler";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6298
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6299
    case counter_loop:            return "loops";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6300
    case counter_block:           return "blocks";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6301
    case counter_loop_block:      return "blocks inside loop";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6302
    case counter_exception_block: return "exception handler entries";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6303
    case counter_interval:        return "intervals";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6304
    case counter_fixed_interval:  return "fixed intervals";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6305
    case counter_range:           return "ranges";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6306
    case counter_fixed_range:     return "fixed ranges";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6307
    case counter_use_pos:         return "use positions";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6308
    case counter_fixed_use_pos:   return "fixed use positions";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6309
    case counter_spill_slots:     return "spill slots";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6310
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6311
    // counter for classes of lir instructions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6312
    case counter_instruction:     return "total instructions";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6313
    case counter_label:           return "labels";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6314
    case counter_entry:           return "method entries";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6315
    case counter_return:          return "method returns";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6316
    case counter_call:            return "method calls";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6317
    case counter_move:            return "moves";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6318
    case counter_cmp:             return "compare";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6319
    case counter_cond_branch:     return "conditional branches";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6320
    case counter_uncond_branch:   return "unconditional branches";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6321
    case counter_stub_branch:     return "branches to stub";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6322
    case counter_alu:             return "artithmetic + logic";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6323
    case counter_alloc:           return "allocations";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6324
    case counter_sync:            return "synchronisation";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6325
    case counter_throw:           return "throw";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6326
    case counter_unwind:          return "unwind";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6327
    case counter_typecheck:       return "type+null-checks";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6328
    case counter_fpu_stack:       return "fpu-stack";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6329
    case counter_misc_inst:       return "other instructions";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6330
    case counter_other_inst:      return "misc. instructions";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6331
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6332
    // counter for different types of moves
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6333
    case counter_move_total:      return "total moves";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6334
    case counter_move_reg_reg:    return "register->register";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6335
    case counter_move_reg_stack:  return "register->stack";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6336
    case counter_move_stack_reg:  return "stack->register";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6337
    case counter_move_stack_stack:return "stack->stack";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6338
    case counter_move_reg_mem:    return "register->memory";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6339
    case counter_move_mem_reg:    return "memory->register";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6340
    case counter_move_const_any:  return "constant->any";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6341
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6342
    case blank_line_1:            return "";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6343
    case blank_line_2:            return "";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6344
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6345
    default: ShouldNotReachHere(); return "";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6346
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6347
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6348
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6349
LinearScanStatistic::Counter LinearScanStatistic::base_counter(int counter_idx) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6350
  if (counter_idx == counter_fpu_method || counter_idx == counter_loop_method || counter_idx == counter_exception_method) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6351
    return counter_method;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6352
  } else if (counter_idx == counter_loop_block || counter_idx == counter_exception_block) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6353
    return counter_block;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6354
  } else if (counter_idx >= counter_instruction && counter_idx <= counter_other_inst) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6355
    return counter_instruction;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6356
  } else if (counter_idx >= counter_move_total && counter_idx <= counter_move_const_any) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6357
    return counter_move_total;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6358
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6359
  return invalid_counter;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6360
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6361
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6362
LinearScanStatistic::LinearScanStatistic() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6363
  for (int i = 0; i < number_of_counters; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6364
    _counters_sum[i] = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6365
    _counters_max[i] = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6366
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6367
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6368
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6369
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6370
// add the method-local numbers to the total sum
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6371
void LinearScanStatistic::sum_up(LinearScanStatistic &method_statistic) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6372
  for (int i = 0; i < number_of_counters; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6373
    _counters_sum[i] += method_statistic._counters_sum[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6374
    _counters_max[i] = MAX2(_counters_max[i], method_statistic._counters_sum[i]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6375
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6376
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6377
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6378
void LinearScanStatistic::print(const char* title) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6379
  if (CountLinearScan || TraceLinearScanLevel > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6380
    tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6381
    tty->print_cr("***** LinearScan statistic - %s *****", title);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6382
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6383
    for (int i = 0; i < number_of_counters; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6384
      if (_counters_sum[i] > 0 || _counters_max[i] >= 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6385
        tty->print("%25s: %8d", counter_name(i), _counters_sum[i]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6386
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6387
        if (base_counter(i) != invalid_counter) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6388
          tty->print("  (%5.1f%%) ", _counters_sum[i] * 100.0 / _counters_sum[base_counter(i)]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6389
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6390
          tty->print("           ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6391
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6392
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6393
        if (_counters_max[i] >= 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6394
          tty->print("%8d", _counters_max[i]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6395
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6396
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6397
      tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6398
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6399
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6400
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6401
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6402
void LinearScanStatistic::collect(LinearScan* allocator) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6403
  inc_counter(counter_method);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6404
  if (allocator->has_fpu_registers()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6405
    inc_counter(counter_fpu_method);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6406
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6407
  if (allocator->num_loops() > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6408
    inc_counter(counter_loop_method);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6409
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6410
  inc_counter(counter_loop, allocator->num_loops());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6411
  inc_counter(counter_spill_slots, allocator->max_spills());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6412
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6413
  int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6414
  for (i = 0; i < allocator->interval_count(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6415
    Interval* cur = allocator->interval_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6416
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6417
    if (cur != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6418
      inc_counter(counter_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6419
      inc_counter(counter_use_pos, cur->num_use_positions());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6420
      if (LinearScan::is_precolored_interval(cur)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6421
        inc_counter(counter_fixed_interval);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6422
        inc_counter(counter_fixed_use_pos, cur->num_use_positions());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6423
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6424
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6425
      Range* range = cur->first();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6426
      while (range != Range::end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6427
        inc_counter(counter_range);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6428
        if (LinearScan::is_precolored_interval(cur)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6429
          inc_counter(counter_fixed_range);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6430
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6431
        range = range->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6432
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6433
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6434
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6435
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6436
  bool has_xhandlers = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6437
  // Note: only count blocks that are in code-emit order
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6438
  for (i = 0; i < allocator->ir()->code()->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6439
    BlockBegin* cur = allocator->ir()->code()->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6440
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6441
    inc_counter(counter_block);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6442
    if (cur->loop_depth() > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6443
      inc_counter(counter_loop_block);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6444
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6445
    if (cur->is_set(BlockBegin::exception_entry_flag)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6446
      inc_counter(counter_exception_block);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6447
      has_xhandlers = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6448
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6449
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6450
    LIR_OpList* instructions = cur->lir()->instructions_list();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6451
    for (int j = 0; j < instructions->length(); j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6452
      LIR_Op* op = instructions->at(j);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6453
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6454
      inc_counter(counter_instruction);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6455
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6456
      switch (op->code()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6457
        case lir_label:           inc_counter(counter_label); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6458
        case lir_std_entry:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6459
        case lir_osr_entry:       inc_counter(counter_entry); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6460
        case lir_return:          inc_counter(counter_return); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6461
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6462
        case lir_rtcall:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6463
        case lir_static_call:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6464
        case lir_optvirtual_call:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6465
        case lir_virtual_call:    inc_counter(counter_call); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6466
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6467
        case lir_move: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6468
          inc_counter(counter_move);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6469
          inc_counter(counter_move_total);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6470
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6471
          LIR_Opr in = op->as_Op1()->in_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6472
          LIR_Opr res = op->as_Op1()->result_opr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6473
          if (in->is_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6474
            if (res->is_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6475
              inc_counter(counter_move_reg_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6476
            } else if (res->is_stack()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6477
              inc_counter(counter_move_reg_stack);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6478
            } else if (res->is_address()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6479
              inc_counter(counter_move_reg_mem);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6480
            } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6481
              ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6482
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6483
          } else if (in->is_stack()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6484
            if (res->is_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6485
              inc_counter(counter_move_stack_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6486
            } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6487
              inc_counter(counter_move_stack_stack);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6488
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6489
          } else if (in->is_address()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6490
            assert(res->is_register(), "must be");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6491
            inc_counter(counter_move_mem_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6492
          } else if (in->is_constant()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6493
            inc_counter(counter_move_const_any);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6494
          } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6495
            ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6496
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6497
          break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6498
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6499
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6500
        case lir_cmp:             inc_counter(counter_cmp); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6501
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6502
        case lir_branch:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6503
        case lir_cond_float_branch: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6504
          LIR_OpBranch* branch = op->as_OpBranch();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6505
          if (branch->block() == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6506
            inc_counter(counter_stub_branch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6507
          } else if (branch->cond() == lir_cond_always) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6508
            inc_counter(counter_uncond_branch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6509
          } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6510
            inc_counter(counter_cond_branch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6511
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6512
          break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6513
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6514
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6515
        case lir_neg:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6516
        case lir_add:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6517
        case lir_sub:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6518
        case lir_mul:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6519
        case lir_mul_strictfp:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6520
        case lir_div:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6521
        case lir_div_strictfp:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6522
        case lir_rem:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6523
        case lir_sqrt:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6524
        case lir_sin:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6525
        case lir_cos:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6526
        case lir_abs:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6527
        case lir_log10:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6528
        case lir_log:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6529
        case lir_logic_and:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6530
        case lir_logic_or:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6531
        case lir_logic_xor:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6532
        case lir_shl:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6533
        case lir_shr:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6534
        case lir_ushr:            inc_counter(counter_alu); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6535
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6536
        case lir_alloc_object:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6537
        case lir_alloc_array:     inc_counter(counter_alloc); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6538
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6539
        case lir_monaddr:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6540
        case lir_lock:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6541
        case lir_unlock:          inc_counter(counter_sync); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6542
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6543
        case lir_throw:           inc_counter(counter_throw); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6544
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6545
        case lir_unwind:          inc_counter(counter_unwind); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6546
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6547
        case lir_null_check:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6548
        case lir_leal:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6549
        case lir_instanceof:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6550
        case lir_checkcast:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6551
        case lir_store_check:     inc_counter(counter_typecheck); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6552
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6553
        case lir_fpop_raw:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6554
        case lir_fxch:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6555
        case lir_fld:             inc_counter(counter_fpu_stack); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6556
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6557
        case lir_nop:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6558
        case lir_push:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6559
        case lir_pop:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6560
        case lir_convert:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6561
        case lir_roundfp:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6562
        case lir_cmove:           inc_counter(counter_misc_inst); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6563
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6564
        default:                  inc_counter(counter_other_inst); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6565
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6566
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6567
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6568
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6569
  if (has_xhandlers) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6570
    inc_counter(counter_exception_method);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6571
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6572
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6573
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6574
void LinearScanStatistic::compute(LinearScan* allocator, LinearScanStatistic &global_statistic) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6575
  if (CountLinearScan || TraceLinearScanLevel > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6576
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6577
    LinearScanStatistic local_statistic = LinearScanStatistic();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6578
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6579
    local_statistic.collect(allocator);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6580
    global_statistic.sum_up(local_statistic);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6581
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6582
    if (TraceLinearScanLevel > 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6583
      local_statistic.print("current local statistic");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6584
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6585
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6586
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6587
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6588
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6589
// Implementation of LinearTimers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6590
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6591
LinearScanTimers::LinearScanTimers() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6592
  for (int i = 0; i < number_of_timers; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6593
    timer(i)->reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6594
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6595
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6596
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6597
const char* LinearScanTimers::timer_name(int idx) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6598
  switch (idx) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6599
    case timer_do_nothing:               return "Nothing (Time Check)";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6600
    case timer_number_instructions:      return "Number Instructions";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6601
    case timer_compute_local_live_sets:  return "Local Live Sets";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6602
    case timer_compute_global_live_sets: return "Global Live Sets";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6603
    case timer_build_intervals:          return "Build Intervals";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6604
    case timer_sort_intervals_before:    return "Sort Intervals Before";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6605
    case timer_allocate_registers:       return "Allocate Registers";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6606
    case timer_resolve_data_flow:        return "Resolve Data Flow";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6607
    case timer_sort_intervals_after:     return "Sort Intervals After";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6608
    case timer_eliminate_spill_moves:    return "Spill optimization";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6609
    case timer_assign_reg_num:           return "Assign Reg Num";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6610
    case timer_allocate_fpu_stack:       return "Allocate FPU Stack";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6611
    case timer_optimize_lir:             return "Optimize LIR";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6612
    default: ShouldNotReachHere();       return "";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6613
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6614
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6615
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6616
void LinearScanTimers::begin_method() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6617
  if (TimeEachLinearScan) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6618
    // reset all timers to measure only current method
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6619
    for (int i = 0; i < number_of_timers; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6620
      timer(i)->reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6621
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6622
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6623
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6624
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6625
void LinearScanTimers::end_method(LinearScan* allocator) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6626
  if (TimeEachLinearScan) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6627
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6628
    double c = timer(timer_do_nothing)->seconds();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6629
    double total = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6630
    for (int i = 1; i < number_of_timers; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6631
      total += timer(i)->seconds() - c;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6632
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6633
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6634
    if (total >= 0.0005) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6635
      // print all information in one line for automatic processing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6636
      tty->print("@"); allocator->compilation()->method()->print_name();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6637
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6638
      tty->print("@ %d ", allocator->compilation()->method()->code_size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6639
      tty->print("@ %d ", allocator->block_at(allocator->block_count() - 1)->last_lir_instruction_id() / 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6640
      tty->print("@ %d ", allocator->block_count());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6641
      tty->print("@ %d ", allocator->num_virtual_regs());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6642
      tty->print("@ %d ", allocator->interval_count());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6643
      tty->print("@ %d ", allocator->_num_calls);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6644
      tty->print("@ %d ", allocator->num_loops());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6645
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6646
      tty->print("@ %6.6f ", total);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6647
      for (int i = 1; i < number_of_timers; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6648
        tty->print("@ %4.1f ", ((timer(i)->seconds() - c) / total) * 100);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6649
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6650
      tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6651
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6652
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6653
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6654
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6655
void LinearScanTimers::print(double total_time) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6656
  if (TimeLinearScan) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6657
    // correction value: sum of dummy-timer that only measures the time that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6658
    // is necesary to start and stop itself
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6659
    double c = timer(timer_do_nothing)->seconds();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6660
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6661
    for (int i = 0; i < number_of_timers; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6662
      double t = timer(i)->seconds();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6663
      tty->print_cr("    %25s: %6.3f s (%4.1f%%)  corrected: %6.3f s (%4.1f%%)", timer_name(i), t, (t / total_time) * 100.0, t - c, (t - c) / (total_time - 2 * number_of_timers * c) * 100);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6664
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6665
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6666
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6667
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6668
#endif // #ifndef PRODUCT