annotate src/share/vm/c1/c1_LinearScan.cpp @ 6862:8a5ea0a9ccc4

7127708: G1: change task num types from int to uint in concurrent mark Summary: Change the type of various task num fields, parameters etc to unsigned and rename them to be more consistent with the other collectors. Code changes were also reviewed by Vitaly Davidovich. Reviewed-by: johnc Contributed-by: Kaushik Srenevasan <kaushik@twitter.com>
author johnc
date Sat, 06 Oct 2012 01:17:44 -0700
parents 8a02ca5e5576
children b9a9ed0f8eeb
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
2426
1d1603768966 7010070: Update all 2010 Oracle-changed OpenJDK files to have the proper copyright dates - second pass
trims
parents: 2345
diff changeset
2 * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1397
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1397
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1397
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
25 #include "precompiled.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
26 #include "c1/c1_CFGPrinter.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
27 #include "c1/c1_CodeStubs.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
28 #include "c1/c1_Compilation.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
29 #include "c1/c1_FrameMap.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
30 #include "c1/c1_IR.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
31 #include "c1/c1_LIRGenerator.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
32 #include "c1/c1_LinearScan.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
33 #include "c1/c1_ValueStack.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
34 #include "utilities/bitMap.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
35 #ifdef TARGET_ARCH_x86
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
36 # include "vmreg_x86.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
37 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
38 #ifdef TARGET_ARCH_sparc
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
39 # include "vmreg_sparc.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
40 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
41 #ifdef TARGET_ARCH_zero
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
42 # include "vmreg_zero.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
43 #endif
2192
b92c45f2bc75 7016023: Enable building ARM and PPC from src/closed repository
bobv
parents: 2081
diff changeset
44 #ifdef TARGET_ARCH_arm
b92c45f2bc75 7016023: Enable building ARM and PPC from src/closed repository
bobv
parents: 2081
diff changeset
45 # include "vmreg_arm.inline.hpp"
b92c45f2bc75 7016023: Enable building ARM and PPC from src/closed repository
bobv
parents: 2081
diff changeset
46 #endif
b92c45f2bc75 7016023: Enable building ARM and PPC from src/closed repository
bobv
parents: 2081
diff changeset
47 #ifdef TARGET_ARCH_ppc
b92c45f2bc75 7016023: Enable building ARM and PPC from src/closed repository
bobv
parents: 2081
diff changeset
48 # include "vmreg_ppc.inline.hpp"
b92c45f2bc75 7016023: Enable building ARM and PPC from src/closed repository
bobv
parents: 2081
diff changeset
49 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
50
a61af66fc99e Initial load
duke
parents:
diff changeset
51
a61af66fc99e Initial load
duke
parents:
diff changeset
52 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
53
a61af66fc99e Initial load
duke
parents:
diff changeset
54 static LinearScanStatistic _stat_before_alloc;
a61af66fc99e Initial load
duke
parents:
diff changeset
55 static LinearScanStatistic _stat_after_asign;
a61af66fc99e Initial load
duke
parents:
diff changeset
56 static LinearScanStatistic _stat_final;
a61af66fc99e Initial load
duke
parents:
diff changeset
57
a61af66fc99e Initial load
duke
parents:
diff changeset
58 static LinearScanTimers _total_timer;
a61af66fc99e Initial load
duke
parents:
diff changeset
59
a61af66fc99e Initial load
duke
parents:
diff changeset
60 // helper macro for short definition of timer
a61af66fc99e Initial load
duke
parents:
diff changeset
61 #define TIME_LINEAR_SCAN(timer_name) TraceTime _block_timer("", _total_timer.timer(LinearScanTimers::timer_name), TimeLinearScan || TimeEachLinearScan, Verbose);
a61af66fc99e Initial load
duke
parents:
diff changeset
62
a61af66fc99e Initial load
duke
parents:
diff changeset
63 // helper macro for short definition of trace-output inside code
a61af66fc99e Initial load
duke
parents:
diff changeset
64 #define TRACE_LINEAR_SCAN(level, code) \
a61af66fc99e Initial load
duke
parents:
diff changeset
65 if (TraceLinearScanLevel >= level) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
66 code; \
a61af66fc99e Initial load
duke
parents:
diff changeset
67 }
a61af66fc99e Initial load
duke
parents:
diff changeset
68
a61af66fc99e Initial load
duke
parents:
diff changeset
69 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
70
a61af66fc99e Initial load
duke
parents:
diff changeset
71 #define TIME_LINEAR_SCAN(timer_name)
a61af66fc99e Initial load
duke
parents:
diff changeset
72 #define TRACE_LINEAR_SCAN(level, code)
a61af66fc99e Initial load
duke
parents:
diff changeset
73
a61af66fc99e Initial load
duke
parents:
diff changeset
74 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 // Map BasicType to spill size in 32-bit words, matching VMReg's notion of words
a61af66fc99e Initial load
duke
parents:
diff changeset
77 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
78 static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 0, 1, -1};
a61af66fc99e Initial load
duke
parents:
diff changeset
79 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
80 static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, -1};
a61af66fc99e Initial load
duke
parents:
diff changeset
81 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
82
a61af66fc99e Initial load
duke
parents:
diff changeset
83
a61af66fc99e Initial load
duke
parents:
diff changeset
84 // Implementation of LinearScan
a61af66fc99e Initial load
duke
parents:
diff changeset
85
a61af66fc99e Initial load
duke
parents:
diff changeset
86 LinearScan::LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map)
a61af66fc99e Initial load
duke
parents:
diff changeset
87 : _compilation(ir->compilation())
a61af66fc99e Initial load
duke
parents:
diff changeset
88 , _ir(ir)
a61af66fc99e Initial load
duke
parents:
diff changeset
89 , _gen(gen)
a61af66fc99e Initial load
duke
parents:
diff changeset
90 , _frame_map(frame_map)
a61af66fc99e Initial load
duke
parents:
diff changeset
91 , _num_virtual_regs(gen->max_virtual_register_number())
a61af66fc99e Initial load
duke
parents:
diff changeset
92 , _has_fpu_registers(false)
a61af66fc99e Initial load
duke
parents:
diff changeset
93 , _num_calls(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
94 , _max_spills(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
95 , _unused_spill_slot(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
96 , _intervals(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
97 , _new_intervals_from_allocation(new IntervalList())
a61af66fc99e Initial load
duke
parents:
diff changeset
98 , _sorted_intervals(NULL)
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
99 , _needs_full_resort(false)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
100 , _lir_ops(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
101 , _block_of_op(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
102 , _has_info(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
103 , _has_call(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
104 , _scope_value_cache(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
105 , _interval_in_loop(0, 0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
106 , _cached_blocks(*ir->linear_scan_order())
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
107 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
108 , _fpu_stack_allocator(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
109 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
110 {
a61af66fc99e Initial load
duke
parents:
diff changeset
111 assert(this->ir() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
112 assert(this->compilation() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
113 assert(this->gen() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
114 assert(this->frame_map() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
116
a61af66fc99e Initial load
duke
parents:
diff changeset
117
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // ********** functions for converting LIR-Operands to register numbers
a61af66fc99e Initial load
duke
parents:
diff changeset
119 //
a61af66fc99e Initial load
duke
parents:
diff changeset
120 // Emulate a flat register file comprising physical integer registers,
a61af66fc99e Initial load
duke
parents:
diff changeset
121 // physical floating-point registers and virtual registers, in that order.
a61af66fc99e Initial load
duke
parents:
diff changeset
122 // Virtual registers already have appropriate numbers, since V0 is
a61af66fc99e Initial load
duke
parents:
diff changeset
123 // the number of physical registers.
a61af66fc99e Initial load
duke
parents:
diff changeset
124 // Returns -1 for hi word if opr is a single word operand.
a61af66fc99e Initial load
duke
parents:
diff changeset
125 //
a61af66fc99e Initial load
duke
parents:
diff changeset
126 // Note: the inverse operation (calculating an operand for register numbers)
a61af66fc99e Initial load
duke
parents:
diff changeset
127 // is done in calc_operand_for_interval()
a61af66fc99e Initial load
duke
parents:
diff changeset
128
a61af66fc99e Initial load
duke
parents:
diff changeset
129 int LinearScan::reg_num(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
130 assert(opr->is_register(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
131
a61af66fc99e Initial load
duke
parents:
diff changeset
132 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
133 assert(opr->vreg_number() >= nof_regs, "found a virtual register with a fixed-register number");
a61af66fc99e Initial load
duke
parents:
diff changeset
134 return opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
135 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
136 return opr->cpu_regnr();
a61af66fc99e Initial load
duke
parents:
diff changeset
137 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
138 return opr->cpu_regnrLo();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
139 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
140 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
141 return opr->fpu_regnr() + pd_first_xmm_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
142 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
143 return opr->fpu_regnrLo() + pd_first_xmm_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
144 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
145 } else if (opr->is_single_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
146 return opr->fpu_regnr() + pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
147 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
148 return opr->fpu_regnrLo() + pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
149 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
150 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
151 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
154
a61af66fc99e Initial load
duke
parents:
diff changeset
155 int LinearScan::reg_numHi(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
156 assert(opr->is_register(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
157
a61af66fc99e Initial load
duke
parents:
diff changeset
158 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
159 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
160 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
161 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
162 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
163 return opr->cpu_regnrHi();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
164 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
165 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
166 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
167 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
168 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
169 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
170 } else if (opr->is_single_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
171 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
172 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
173 return opr->fpu_regnrHi() + pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
174 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
175 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
176 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
177 }
a61af66fc99e Initial load
duke
parents:
diff changeset
178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
179
a61af66fc99e Initial load
duke
parents:
diff changeset
180
a61af66fc99e Initial load
duke
parents:
diff changeset
181 // ********** functions for classification of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
182
a61af66fc99e Initial load
duke
parents:
diff changeset
183 bool LinearScan::is_precolored_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
184 return i->reg_num() < LinearScan::nof_regs;
a61af66fc99e Initial load
duke
parents:
diff changeset
185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
186
a61af66fc99e Initial load
duke
parents:
diff changeset
187 bool LinearScan::is_virtual_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
188 return i->reg_num() >= LIR_OprDesc::vreg_base;
a61af66fc99e Initial load
duke
parents:
diff changeset
189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
190
a61af66fc99e Initial load
duke
parents:
diff changeset
191 bool LinearScan::is_precolored_cpu_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
192 return i->reg_num() < LinearScan::nof_cpu_regs;
a61af66fc99e Initial load
duke
parents:
diff changeset
193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
194
a61af66fc99e Initial load
duke
parents:
diff changeset
195 bool LinearScan::is_virtual_cpu_interval(const Interval* i) {
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
196 #if defined(__SOFTFP__) || defined(E500V2)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
197 return i->reg_num() >= LIR_OprDesc::vreg_base;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
198 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
199 return i->reg_num() >= LIR_OprDesc::vreg_base && (i->type() != T_FLOAT && i->type() != T_DOUBLE);
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
200 #endif // __SOFTFP__ or E500V2
0
a61af66fc99e Initial load
duke
parents:
diff changeset
201 }
a61af66fc99e Initial load
duke
parents:
diff changeset
202
a61af66fc99e Initial load
duke
parents:
diff changeset
203 bool LinearScan::is_precolored_fpu_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
204 return i->reg_num() >= LinearScan::nof_cpu_regs && i->reg_num() < LinearScan::nof_regs;
a61af66fc99e Initial load
duke
parents:
diff changeset
205 }
a61af66fc99e Initial load
duke
parents:
diff changeset
206
a61af66fc99e Initial load
duke
parents:
diff changeset
207 bool LinearScan::is_virtual_fpu_interval(const Interval* i) {
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
208 #if defined(__SOFTFP__) || defined(E500V2)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
209 return false;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
210 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
211 return i->reg_num() >= LIR_OprDesc::vreg_base && (i->type() == T_FLOAT || i->type() == T_DOUBLE);
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
212 #endif // __SOFTFP__ or E500V2
0
a61af66fc99e Initial load
duke
parents:
diff changeset
213 }
a61af66fc99e Initial load
duke
parents:
diff changeset
214
a61af66fc99e Initial load
duke
parents:
diff changeset
215 bool LinearScan::is_in_fpu_register(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
216 // fixed intervals not needed for FPU stack allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
217 return i->reg_num() >= nof_regs && pd_first_fpu_reg <= i->assigned_reg() && i->assigned_reg() <= pd_last_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
218 }
a61af66fc99e Initial load
duke
parents:
diff changeset
219
a61af66fc99e Initial load
duke
parents:
diff changeset
220 bool LinearScan::is_oop_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
221 // fixed intervals never contain oops
a61af66fc99e Initial load
duke
parents:
diff changeset
222 return i->reg_num() >= nof_regs && i->type() == T_OBJECT;
a61af66fc99e Initial load
duke
parents:
diff changeset
223 }
a61af66fc99e Initial load
duke
parents:
diff changeset
224
a61af66fc99e Initial load
duke
parents:
diff changeset
225
a61af66fc99e Initial load
duke
parents:
diff changeset
226 // ********** General helper functions
a61af66fc99e Initial load
duke
parents:
diff changeset
227
a61af66fc99e Initial load
duke
parents:
diff changeset
228 // compute next unused stack index that can be used for spilling
a61af66fc99e Initial load
duke
parents:
diff changeset
229 int LinearScan::allocate_spill_slot(bool double_word) {
a61af66fc99e Initial load
duke
parents:
diff changeset
230 int spill_slot;
a61af66fc99e Initial load
duke
parents:
diff changeset
231 if (double_word) {
a61af66fc99e Initial load
duke
parents:
diff changeset
232 if ((_max_spills & 1) == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
233 // alignment of double-word values
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // the hole because of the alignment is filled with the next single-word value
a61af66fc99e Initial load
duke
parents:
diff changeset
235 assert(_unused_spill_slot == -1, "wasting a spill slot");
a61af66fc99e Initial load
duke
parents:
diff changeset
236 _unused_spill_slot = _max_spills;
a61af66fc99e Initial load
duke
parents:
diff changeset
237 _max_spills++;
a61af66fc99e Initial load
duke
parents:
diff changeset
238 }
a61af66fc99e Initial load
duke
parents:
diff changeset
239 spill_slot = _max_spills;
a61af66fc99e Initial load
duke
parents:
diff changeset
240 _max_spills += 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
241
a61af66fc99e Initial load
duke
parents:
diff changeset
242 } else if (_unused_spill_slot != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
243 // re-use hole that was the result of a previous double-word alignment
a61af66fc99e Initial load
duke
parents:
diff changeset
244 spill_slot = _unused_spill_slot;
a61af66fc99e Initial load
duke
parents:
diff changeset
245 _unused_spill_slot = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
246
a61af66fc99e Initial load
duke
parents:
diff changeset
247 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
248 spill_slot = _max_spills;
a61af66fc99e Initial load
duke
parents:
diff changeset
249 _max_spills++;
a61af66fc99e Initial load
duke
parents:
diff changeset
250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
251
a61af66fc99e Initial load
duke
parents:
diff changeset
252 int result = spill_slot + LinearScan::nof_regs + frame_map()->argcount();
a61af66fc99e Initial load
duke
parents:
diff changeset
253
a61af66fc99e Initial load
duke
parents:
diff changeset
254 // the class OopMapValue uses only 11 bits for storing the name of the
a61af66fc99e Initial load
duke
parents:
diff changeset
255 // oop location. So a stack slot bigger than 2^11 leads to an overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
256 // that is not reported in product builds. Prevent this by checking the
a61af66fc99e Initial load
duke
parents:
diff changeset
257 // spill slot here (altough this value and the later used location name
a61af66fc99e Initial load
duke
parents:
diff changeset
258 // are slightly different)
a61af66fc99e Initial load
duke
parents:
diff changeset
259 if (result > 2000) {
a61af66fc99e Initial load
duke
parents:
diff changeset
260 bailout("too many stack slots used");
a61af66fc99e Initial load
duke
parents:
diff changeset
261 }
a61af66fc99e Initial load
duke
parents:
diff changeset
262
a61af66fc99e Initial load
duke
parents:
diff changeset
263 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
264 }
a61af66fc99e Initial load
duke
parents:
diff changeset
265
a61af66fc99e Initial load
duke
parents:
diff changeset
266 void LinearScan::assign_spill_slot(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
267 // assign the canonical spill slot of the parent (if a part of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
268 // is already spilled) or allocate a new spill slot
a61af66fc99e Initial load
duke
parents:
diff changeset
269 if (it->canonical_spill_slot() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
270 it->assign_reg(it->canonical_spill_slot());
a61af66fc99e Initial load
duke
parents:
diff changeset
271 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
272 int spill = allocate_spill_slot(type2spill_size[it->type()] == 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
273 it->set_canonical_spill_slot(spill);
a61af66fc99e Initial load
duke
parents:
diff changeset
274 it->assign_reg(spill);
a61af66fc99e Initial load
duke
parents:
diff changeset
275 }
a61af66fc99e Initial load
duke
parents:
diff changeset
276 }
a61af66fc99e Initial load
duke
parents:
diff changeset
277
a61af66fc99e Initial load
duke
parents:
diff changeset
278 void LinearScan::propagate_spill_slots() {
a61af66fc99e Initial load
duke
parents:
diff changeset
279 if (!frame_map()->finalize_frame(max_spills())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
280 bailout("frame too large");
a61af66fc99e Initial load
duke
parents:
diff changeset
281 }
a61af66fc99e Initial load
duke
parents:
diff changeset
282 }
a61af66fc99e Initial load
duke
parents:
diff changeset
283
a61af66fc99e Initial load
duke
parents:
diff changeset
284 // create a new interval with a predefined reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
285 // (only used for parent intervals that are created during the building phase)
a61af66fc99e Initial load
duke
parents:
diff changeset
286 Interval* LinearScan::create_interval(int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
287 assert(_intervals.at(reg_num) == NULL, "overwriting exisiting interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
288
a61af66fc99e Initial load
duke
parents:
diff changeset
289 Interval* interval = new Interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
290 _intervals.at_put(reg_num, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
291
a61af66fc99e Initial load
duke
parents:
diff changeset
292 // assign register number for precolored intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
293 if (reg_num < LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
294 interval->assign_reg(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
295 }
a61af66fc99e Initial load
duke
parents:
diff changeset
296 return interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
297 }
a61af66fc99e Initial load
duke
parents:
diff changeset
298
a61af66fc99e Initial load
duke
parents:
diff changeset
299 // assign a new reg_num to the interval and append it to the list of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // (only used for child intervals that are created during register allocation)
a61af66fc99e Initial load
duke
parents:
diff changeset
301 void LinearScan::append_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
302 it->set_reg_num(_intervals.length());
a61af66fc99e Initial load
duke
parents:
diff changeset
303 _intervals.append(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
304 _new_intervals_from_allocation->append(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
305 }
a61af66fc99e Initial load
duke
parents:
diff changeset
306
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // copy the vreg-flags if an interval is split
a61af66fc99e Initial load
duke
parents:
diff changeset
308 void LinearScan::copy_register_flags(Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
309 if (gen()->is_vreg_flag_set(from->reg_num(), LIRGenerator::byte_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
310 gen()->set_vreg_flag(to->reg_num(), LIRGenerator::byte_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
311 }
a61af66fc99e Initial load
duke
parents:
diff changeset
312 if (gen()->is_vreg_flag_set(from->reg_num(), LIRGenerator::callee_saved)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
313 gen()->set_vreg_flag(to->reg_num(), LIRGenerator::callee_saved);
a61af66fc99e Initial load
duke
parents:
diff changeset
314 }
a61af66fc99e Initial load
duke
parents:
diff changeset
315
a61af66fc99e Initial load
duke
parents:
diff changeset
316 // Note: do not copy the must_start_in_memory flag because it is not necessary for child
a61af66fc99e Initial load
duke
parents:
diff changeset
317 // intervals (only the very beginning of the interval must be in memory)
a61af66fc99e Initial load
duke
parents:
diff changeset
318 }
a61af66fc99e Initial load
duke
parents:
diff changeset
319
a61af66fc99e Initial load
duke
parents:
diff changeset
320
a61af66fc99e Initial load
duke
parents:
diff changeset
321 // ********** spill move optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
322 // eliminate moves from register to stack if stack slot is known to be correct
a61af66fc99e Initial load
duke
parents:
diff changeset
323
a61af66fc99e Initial load
duke
parents:
diff changeset
324 // called during building of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
325 void LinearScan::change_spill_definition_pos(Interval* interval, int def_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
326 assert(interval->is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
327
a61af66fc99e Initial load
duke
parents:
diff changeset
328 switch (interval->spill_state()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
329 case noDefinitionFound:
a61af66fc99e Initial load
duke
parents:
diff changeset
330 assert(interval->spill_definition_pos() == -1, "must no be set before");
a61af66fc99e Initial load
duke
parents:
diff changeset
331 interval->set_spill_definition_pos(def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
332 interval->set_spill_state(oneDefinitionFound);
a61af66fc99e Initial load
duke
parents:
diff changeset
333 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
334
a61af66fc99e Initial load
duke
parents:
diff changeset
335 case oneDefinitionFound:
a61af66fc99e Initial load
duke
parents:
diff changeset
336 assert(def_pos <= interval->spill_definition_pos(), "positions are processed in reverse order when intervals are created");
a61af66fc99e Initial load
duke
parents:
diff changeset
337 if (def_pos < interval->spill_definition_pos() - 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
338 // second definition found, so no spill optimization possible for this interval
a61af66fc99e Initial load
duke
parents:
diff changeset
339 interval->set_spill_state(noOptimization);
a61af66fc99e Initial load
duke
parents:
diff changeset
340 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
341 // two consecutive definitions (because of two-operand LIR form)
a61af66fc99e Initial load
duke
parents:
diff changeset
342 assert(block_of_op_with_id(def_pos) == block_of_op_with_id(interval->spill_definition_pos()), "block must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
343 }
a61af66fc99e Initial load
duke
parents:
diff changeset
344 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
345
a61af66fc99e Initial load
duke
parents:
diff changeset
346 case noOptimization:
a61af66fc99e Initial load
duke
parents:
diff changeset
347 // nothing to do
a61af66fc99e Initial load
duke
parents:
diff changeset
348 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
349
a61af66fc99e Initial load
duke
parents:
diff changeset
350 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
351 assert(false, "other states not allowed at this time");
a61af66fc99e Initial load
duke
parents:
diff changeset
352 }
a61af66fc99e Initial load
duke
parents:
diff changeset
353 }
a61af66fc99e Initial load
duke
parents:
diff changeset
354
a61af66fc99e Initial load
duke
parents:
diff changeset
355 // called during register allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
356 void LinearScan::change_spill_state(Interval* interval, int spill_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
357 switch (interval->spill_state()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
358 case oneDefinitionFound: {
a61af66fc99e Initial load
duke
parents:
diff changeset
359 int def_loop_depth = block_of_op_with_id(interval->spill_definition_pos())->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
360 int spill_loop_depth = block_of_op_with_id(spill_pos)->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
361
a61af66fc99e Initial load
duke
parents:
diff changeset
362 if (def_loop_depth < spill_loop_depth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
363 // the loop depth of the spilling position is higher then the loop depth
a61af66fc99e Initial load
duke
parents:
diff changeset
364 // at the definition of the interval -> move write to memory out of loop
a61af66fc99e Initial load
duke
parents:
diff changeset
365 // by storing at definitin of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
366 interval->set_spill_state(storeAtDefinition);
a61af66fc99e Initial load
duke
parents:
diff changeset
367 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
368 // the interval is currently spilled only once, so for now there is no
a61af66fc99e Initial load
duke
parents:
diff changeset
369 // reason to store the interval at the definition
a61af66fc99e Initial load
duke
parents:
diff changeset
370 interval->set_spill_state(oneMoveInserted);
a61af66fc99e Initial load
duke
parents:
diff changeset
371 }
a61af66fc99e Initial load
duke
parents:
diff changeset
372 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
373 }
a61af66fc99e Initial load
duke
parents:
diff changeset
374
a61af66fc99e Initial load
duke
parents:
diff changeset
375 case oneMoveInserted: {
a61af66fc99e Initial load
duke
parents:
diff changeset
376 // the interval is spilled more then once, so it is better to store it to
a61af66fc99e Initial load
duke
parents:
diff changeset
377 // memory at the definition
a61af66fc99e Initial load
duke
parents:
diff changeset
378 interval->set_spill_state(storeAtDefinition);
a61af66fc99e Initial load
duke
parents:
diff changeset
379 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
380 }
a61af66fc99e Initial load
duke
parents:
diff changeset
381
a61af66fc99e Initial load
duke
parents:
diff changeset
382 case storeAtDefinition:
a61af66fc99e Initial load
duke
parents:
diff changeset
383 case startInMemory:
a61af66fc99e Initial load
duke
parents:
diff changeset
384 case noOptimization:
a61af66fc99e Initial load
duke
parents:
diff changeset
385 case noDefinitionFound:
a61af66fc99e Initial load
duke
parents:
diff changeset
386 // nothing to do
a61af66fc99e Initial load
duke
parents:
diff changeset
387 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
388
a61af66fc99e Initial load
duke
parents:
diff changeset
389 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
390 assert(false, "other states not allowed at this time");
a61af66fc99e Initial load
duke
parents:
diff changeset
391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
392 }
a61af66fc99e Initial load
duke
parents:
diff changeset
393
a61af66fc99e Initial load
duke
parents:
diff changeset
394
a61af66fc99e Initial load
duke
parents:
diff changeset
395 bool LinearScan::must_store_at_definition(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
396 return i->is_split_parent() && i->spill_state() == storeAtDefinition;
a61af66fc99e Initial load
duke
parents:
diff changeset
397 }
a61af66fc99e Initial load
duke
parents:
diff changeset
398
a61af66fc99e Initial load
duke
parents:
diff changeset
399 // called once before asignment of register numbers
a61af66fc99e Initial load
duke
parents:
diff changeset
400 void LinearScan::eliminate_spill_moves() {
a61af66fc99e Initial load
duke
parents:
diff changeset
401 TIME_LINEAR_SCAN(timer_eliminate_spill_moves);
a61af66fc99e Initial load
duke
parents:
diff changeset
402 TRACE_LINEAR_SCAN(3, tty->print_cr("***** Eliminating unnecessary spill moves"));
a61af66fc99e Initial load
duke
parents:
diff changeset
403
a61af66fc99e Initial load
duke
parents:
diff changeset
404 // collect all intervals that must be stored after their definion.
a61af66fc99e Initial load
duke
parents:
diff changeset
405 // the list is sorted by Interval::spill_definition_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
406 Interval* interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
407 Interval* temp_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
408 create_unhandled_lists(&interval, &temp_list, must_store_at_definition, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
409
a61af66fc99e Initial load
duke
parents:
diff changeset
410 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
411 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
412 Interval* temp = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
413 while (temp != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
414 assert(temp->spill_definition_pos() > 0, "invalid spill definition pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
415 if (prev != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
416 assert(temp->from() >= prev->from(), "intervals not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
417 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");
a61af66fc99e Initial load
duke
parents:
diff changeset
418 }
a61af66fc99e Initial load
duke
parents:
diff changeset
419
a61af66fc99e Initial load
duke
parents:
diff changeset
420 assert(temp->canonical_spill_slot() >= LinearScan::nof_regs, "interval has no spill slot assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
421 assert(temp->spill_definition_pos() >= temp->from(), "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
422 assert(temp->spill_definition_pos() <= temp->from() + 2, "only intervals defined once at their start-pos can be optimized");
a61af66fc99e Initial load
duke
parents:
diff changeset
423
a61af66fc99e Initial load
duke
parents:
diff changeset
424 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
425
a61af66fc99e Initial load
duke
parents:
diff changeset
426 temp = temp->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
427 }
a61af66fc99e Initial load
duke
parents:
diff changeset
428 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
429
a61af66fc99e Initial load
duke
parents:
diff changeset
430 LIR_InsertionBuffer insertion_buffer;
a61af66fc99e Initial load
duke
parents:
diff changeset
431 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
432 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
433 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
434 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
435 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
436 bool has_new = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
437
a61af66fc99e Initial load
duke
parents:
diff changeset
438 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
439 for (int j = 1; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
440 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
441 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
442
a61af66fc99e Initial load
duke
parents:
diff changeset
443 if (op_id == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
444 // remove move from register to stack if the stack slot is guaranteed to be correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
445 // only moves that have been inserted by LinearScan can be removed.
a61af66fc99e Initial load
duke
parents:
diff changeset
446 assert(op->code() == lir_move, "only moves can have a op_id of -1");
a61af66fc99e Initial load
duke
parents:
diff changeset
447 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
448 assert(op->as_Op1()->result_opr()->is_virtual(), "LinearScan inserts only moves to virtual registers");
a61af66fc99e Initial load
duke
parents:
diff changeset
449
a61af66fc99e Initial load
duke
parents:
diff changeset
450 LIR_Op1* op1 = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
451 Interval* interval = interval_at(op1->result_opr()->vreg_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
452
a61af66fc99e Initial load
duke
parents:
diff changeset
453 if (interval->assigned_reg() >= LinearScan::nof_regs && interval->always_in_memory()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
454 // move target is a stack slot that is always correct, so eliminate instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
455 TRACE_LINEAR_SCAN(4, tty->print_cr("eliminating move from interval %d to %d", op1->in_opr()->vreg_number(), op1->result_opr()->vreg_number()));
a61af66fc99e Initial load
duke
parents:
diff changeset
456 instructions->at_put(j, NULL); // NULL-instructions are deleted by assign_reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
457 }
a61af66fc99e Initial load
duke
parents:
diff changeset
458
a61af66fc99e Initial load
duke
parents:
diff changeset
459 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
460 // insert move from register to stack just after the beginning of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
461 assert(interval == Interval::end() || interval->spill_definition_pos() >= op_id, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
462 assert(interval == Interval::end() || (interval->is_split_parent() && interval->spill_state() == storeAtDefinition), "invalid interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
463
a61af66fc99e Initial load
duke
parents:
diff changeset
464 while (interval != Interval::end() && interval->spill_definition_pos() == op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
465 if (!has_new) {
a61af66fc99e Initial load
duke
parents:
diff changeset
466 // prepare insertion buffer (appended when all instructions of the block are processed)
a61af66fc99e Initial load
duke
parents:
diff changeset
467 insertion_buffer.init(block->lir());
a61af66fc99e Initial load
duke
parents:
diff changeset
468 has_new = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
469 }
a61af66fc99e Initial load
duke
parents:
diff changeset
470
a61af66fc99e Initial load
duke
parents:
diff changeset
471 LIR_Opr from_opr = operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
472 LIR_Opr to_opr = canonical_spill_opr(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
473 assert(from_opr->is_fixed_cpu() || from_opr->is_fixed_fpu(), "from operand must be a register");
a61af66fc99e Initial load
duke
parents:
diff changeset
474 assert(to_opr->is_stack(), "to operand must be a stack slot");
a61af66fc99e Initial load
duke
parents:
diff changeset
475
a61af66fc99e Initial load
duke
parents:
diff changeset
476 insertion_buffer.move(j, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
477 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));
a61af66fc99e Initial load
duke
parents:
diff changeset
478
a61af66fc99e Initial load
duke
parents:
diff changeset
479 interval = interval->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
481 }
a61af66fc99e Initial load
duke
parents:
diff changeset
482 } // end of instruction iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
483
a61af66fc99e Initial load
duke
parents:
diff changeset
484 if (has_new) {
a61af66fc99e Initial load
duke
parents:
diff changeset
485 block->lir()->append(&insertion_buffer);
a61af66fc99e Initial load
duke
parents:
diff changeset
486 }
a61af66fc99e Initial load
duke
parents:
diff changeset
487 } // end of block iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
488
a61af66fc99e Initial load
duke
parents:
diff changeset
489 assert(interval == Interval::end(), "missed an interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
490 }
a61af66fc99e Initial load
duke
parents:
diff changeset
491
a61af66fc99e Initial load
duke
parents:
diff changeset
492
a61af66fc99e Initial load
duke
parents:
diff changeset
493 // ********** Phase 1: number all instructions in all blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
494 // Compute depth-first and linear scan block orders, and number LIR_Op nodes for linear scan.
a61af66fc99e Initial load
duke
parents:
diff changeset
495
a61af66fc99e Initial load
duke
parents:
diff changeset
496 void LinearScan::number_instructions() {
a61af66fc99e Initial load
duke
parents:
diff changeset
497 {
a61af66fc99e Initial load
duke
parents:
diff changeset
498 // dummy-timer to measure the cost of the timer itself
a61af66fc99e Initial load
duke
parents:
diff changeset
499 // (this time is then subtracted from all other timers to get the real value)
a61af66fc99e Initial load
duke
parents:
diff changeset
500 TIME_LINEAR_SCAN(timer_do_nothing);
a61af66fc99e Initial load
duke
parents:
diff changeset
501 }
a61af66fc99e Initial load
duke
parents:
diff changeset
502 TIME_LINEAR_SCAN(timer_number_instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
503
a61af66fc99e Initial load
duke
parents:
diff changeset
504 // Assign IDs to LIR nodes and build a mapping, lir_ops, from ID to LIR_Op node.
a61af66fc99e Initial load
duke
parents:
diff changeset
505 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
506 int num_instructions = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
507 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
508 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
509 num_instructions += block_at(i)->lir()->instructions_list()->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
510 }
a61af66fc99e Initial load
duke
parents:
diff changeset
511
a61af66fc99e Initial load
duke
parents:
diff changeset
512 // initialize with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
513 _lir_ops = LIR_OpArray(num_instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
514 _block_of_op = BlockBeginArray(num_instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
515
a61af66fc99e Initial load
duke
parents:
diff changeset
516 int op_id = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
517 int idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
518
a61af66fc99e Initial load
duke
parents:
diff changeset
519 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
520 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
521 block->set_first_lir_instruction_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
522 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
523
a61af66fc99e Initial load
duke
parents:
diff changeset
524 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
525 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
526 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
527 op->set_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
528
a61af66fc99e Initial load
duke
parents:
diff changeset
529 _lir_ops.at_put(idx, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
530 _block_of_op.at_put(idx, block);
a61af66fc99e Initial load
duke
parents:
diff changeset
531 assert(lir_op_with_id(op_id) == op, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
532
a61af66fc99e Initial load
duke
parents:
diff changeset
533 idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
534 op_id += 2; // numbering of lir_ops by two
a61af66fc99e Initial load
duke
parents:
diff changeset
535 }
a61af66fc99e Initial load
duke
parents:
diff changeset
536 block->set_last_lir_instruction_id(op_id - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
537 }
a61af66fc99e Initial load
duke
parents:
diff changeset
538 assert(idx == num_instructions, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
539 assert(idx * 2 == op_id, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
540
a61af66fc99e Initial load
duke
parents:
diff changeset
541 _has_call = BitMap(num_instructions); _has_call.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
542 _has_info = BitMap(num_instructions); _has_info.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
543 }
a61af66fc99e Initial load
duke
parents:
diff changeset
544
a61af66fc99e Initial load
duke
parents:
diff changeset
545
a61af66fc99e Initial load
duke
parents:
diff changeset
546 // ********** Phase 2: compute local live sets separately for each block
a61af66fc99e Initial load
duke
parents:
diff changeset
547 // (sets live_gen and live_kill for each block)
a61af66fc99e Initial load
duke
parents:
diff changeset
548
a61af66fc99e Initial load
duke
parents:
diff changeset
549 void LinearScan::set_live_gen_kill(Value value, LIR_Op* op, BitMap& live_gen, BitMap& live_kill) {
a61af66fc99e Initial load
duke
parents:
diff changeset
550 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
551 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
552
a61af66fc99e Initial load
duke
parents:
diff changeset
553 // check some asumptions about debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
554 assert(!value->type()->is_illegal(), "if this local is used by the interpreter it shouldn't be of indeterminate type");
a61af66fc99e Initial load
duke
parents:
diff changeset
555 assert(con == NULL || opr->is_virtual() || opr->is_constant() || opr->is_illegal(), "asumption: Constant instructions have only constant operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
556 assert(con != NULL || opr->is_virtual(), "asumption: non-Constant instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
557
a61af66fc99e Initial load
duke
parents:
diff changeset
558 if ((con == NULL || con->is_pinned()) && opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
559 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
560 int reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
561 if (!live_kill.at(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
562 live_gen.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
563 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));
a61af66fc99e Initial load
duke
parents:
diff changeset
564 }
a61af66fc99e Initial load
duke
parents:
diff changeset
565 }
a61af66fc99e Initial load
duke
parents:
diff changeset
566 }
a61af66fc99e Initial load
duke
parents:
diff changeset
567
a61af66fc99e Initial load
duke
parents:
diff changeset
568
a61af66fc99e Initial load
duke
parents:
diff changeset
569 void LinearScan::compute_local_live_sets() {
a61af66fc99e Initial load
duke
parents:
diff changeset
570 TIME_LINEAR_SCAN(timer_compute_local_live_sets);
a61af66fc99e Initial load
duke
parents:
diff changeset
571
a61af66fc99e Initial load
duke
parents:
diff changeset
572 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
573 int live_size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
574 bool local_has_fpu_registers = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
575 int local_num_calls = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
576 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
577
a61af66fc99e Initial load
duke
parents:
diff changeset
578 BitMap2D local_interval_in_loop = BitMap2D(_num_virtual_regs, num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
579 local_interval_in_loop.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
580
a61af66fc99e Initial load
duke
parents:
diff changeset
581 // iterate all blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
582 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
583 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
584
a61af66fc99e Initial load
duke
parents:
diff changeset
585 BitMap live_gen(live_size); live_gen.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
586 BitMap live_kill(live_size); live_kill.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
587
a61af66fc99e Initial load
duke
parents:
diff changeset
588 if (block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
589 // Phi functions at the begin of an exception handler are
a61af66fc99e Initial load
duke
parents:
diff changeset
590 // implicitly defined (= killed) at the beginning of the block.
a61af66fc99e Initial load
duke
parents:
diff changeset
591 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
592 live_kill.set_bit(phi->operand()->vreg_number())
a61af66fc99e Initial load
duke
parents:
diff changeset
593 );
a61af66fc99e Initial load
duke
parents:
diff changeset
594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
595
a61af66fc99e Initial load
duke
parents:
diff changeset
596 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
597 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
598
a61af66fc99e Initial load
duke
parents:
diff changeset
599 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
600 assert(visitor.no_operands(instructions->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
601 for (int j = 1; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
602 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
603
a61af66fc99e Initial load
duke
parents:
diff changeset
604 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
605 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
606
a61af66fc99e Initial load
duke
parents:
diff changeset
607 if (visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
608 _has_call.set_bit(op->id() >> 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
609 local_num_calls++;
a61af66fc99e Initial load
duke
parents:
diff changeset
610 }
a61af66fc99e Initial load
duke
parents:
diff changeset
611 if (visitor.info_count() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
612 _has_info.set_bit(op->id() >> 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
613 }
a61af66fc99e Initial load
duke
parents:
diff changeset
614
a61af66fc99e Initial load
duke
parents:
diff changeset
615 // iterate input operands of instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
616 int k, n, reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
617 n = visitor.opr_count(LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
618 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
619 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
620 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
621
a61af66fc99e Initial load
duke
parents:
diff changeset
622 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
623 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
624 reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
625 if (!live_kill.at(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
626 live_gen.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
627 TRACE_LINEAR_SCAN(4, tty->print_cr(" Setting live_gen for register %d at instruction %d", reg, op->id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
628 }
a61af66fc99e Initial load
duke
parents:
diff changeset
629 if (block->loop_index() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
630 local_interval_in_loop.set_bit(reg, block->loop_index());
a61af66fc99e Initial load
duke
parents:
diff changeset
631 }
a61af66fc99e Initial load
duke
parents:
diff changeset
632 local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
a61af66fc99e Initial load
duke
parents:
diff changeset
633 }
a61af66fc99e Initial load
duke
parents:
diff changeset
634
a61af66fc99e Initial load
duke
parents:
diff changeset
635 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
636 // fixed intervals are never live at block boundaries, so
a61af66fc99e Initial load
duke
parents:
diff changeset
637 // they need not be processed in live sets.
a61af66fc99e Initial load
duke
parents:
diff changeset
638 // this is checked by these assertions to be sure about it.
a61af66fc99e Initial load
duke
parents:
diff changeset
639 // the entry block may have incoming values in registers, which is ok.
a61af66fc99e Initial load
duke
parents:
diff changeset
640 if (!opr->is_virtual_register() && block != ir()->start()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
641 reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
642 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
643 assert(live_kill.at(reg), "using fixed register that is not defined in this block");
a61af66fc99e Initial load
duke
parents:
diff changeset
644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
645 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
646 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
647 assert(live_kill.at(reg), "using fixed register that is not defined in this block");
a61af66fc99e Initial load
duke
parents:
diff changeset
648 }
a61af66fc99e Initial load
duke
parents:
diff changeset
649 }
a61af66fc99e Initial load
duke
parents:
diff changeset
650 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
651 }
a61af66fc99e Initial load
duke
parents:
diff changeset
652
a61af66fc99e Initial load
duke
parents:
diff changeset
653 // Add uses of live locals from interpreter's point of view for proper debug information generation
a61af66fc99e Initial load
duke
parents:
diff changeset
654 n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
655 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
656 CodeEmitInfo* info = visitor.info_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
657 ValueStack* stack = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
658 for_each_state_value(stack, value,
a61af66fc99e Initial load
duke
parents:
diff changeset
659 set_live_gen_kill(value, op, live_gen, live_kill)
a61af66fc99e Initial load
duke
parents:
diff changeset
660 );
a61af66fc99e Initial load
duke
parents:
diff changeset
661 }
a61af66fc99e Initial load
duke
parents:
diff changeset
662
a61af66fc99e Initial load
duke
parents:
diff changeset
663 // iterate temp operands of instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
664 n = visitor.opr_count(LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
665 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
666 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
667 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
668
a61af66fc99e Initial load
duke
parents:
diff changeset
669 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
670 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
671 reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
672 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
673 if (block->loop_index() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
674 local_interval_in_loop.set_bit(reg, block->loop_index());
a61af66fc99e Initial load
duke
parents:
diff changeset
675 }
a61af66fc99e Initial load
duke
parents:
diff changeset
676 local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
a61af66fc99e Initial load
duke
parents:
diff changeset
677 }
a61af66fc99e Initial load
duke
parents:
diff changeset
678
a61af66fc99e Initial load
duke
parents:
diff changeset
679 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
680 // fixed intervals are never live at block boundaries, so
a61af66fc99e Initial load
duke
parents:
diff changeset
681 // they need not be processed in live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
682 // process them only in debug mode so that this can be checked
a61af66fc99e Initial load
duke
parents:
diff changeset
683 if (!opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
684 reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
685 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
686 live_kill.set_bit(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
687 }
a61af66fc99e Initial load
duke
parents:
diff changeset
688 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
689 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
690 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
691 }
a61af66fc99e Initial load
duke
parents:
diff changeset
692 }
a61af66fc99e Initial load
duke
parents:
diff changeset
693 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
694 }
a61af66fc99e Initial load
duke
parents:
diff changeset
695
a61af66fc99e Initial load
duke
parents:
diff changeset
696 // iterate output operands of instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
697 n = visitor.opr_count(LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
698 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
699 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
700 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
701
a61af66fc99e Initial load
duke
parents:
diff changeset
702 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
703 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
704 reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
705 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
706 if (block->loop_index() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
707 local_interval_in_loop.set_bit(reg, block->loop_index());
a61af66fc99e Initial load
duke
parents:
diff changeset
708 }
a61af66fc99e Initial load
duke
parents:
diff changeset
709 local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
a61af66fc99e Initial load
duke
parents:
diff changeset
710 }
a61af66fc99e Initial load
duke
parents:
diff changeset
711
a61af66fc99e Initial load
duke
parents:
diff changeset
712 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
713 // fixed intervals are never live at block boundaries, so
a61af66fc99e Initial load
duke
parents:
diff changeset
714 // they need not be processed in live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
715 // process them only in debug mode so that this can be checked
a61af66fc99e Initial load
duke
parents:
diff changeset
716 if (!opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
717 reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
718 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
719 live_kill.set_bit(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
720 }
a61af66fc99e Initial load
duke
parents:
diff changeset
721 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
722 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
723 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
724 }
a61af66fc99e Initial load
duke
parents:
diff changeset
725 }
a61af66fc99e Initial load
duke
parents:
diff changeset
726 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
727 }
a61af66fc99e Initial load
duke
parents:
diff changeset
728 } // end of instruction iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
729
a61af66fc99e Initial load
duke
parents:
diff changeset
730 block->set_live_gen (live_gen);
a61af66fc99e Initial load
duke
parents:
diff changeset
731 block->set_live_kill(live_kill);
a61af66fc99e Initial load
duke
parents:
diff changeset
732 block->set_live_in (BitMap(live_size)); block->live_in().clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
733 block->set_live_out (BitMap(live_size)); block->live_out().clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
734
a61af66fc99e Initial load
duke
parents:
diff changeset
735 TRACE_LINEAR_SCAN(4, tty->print("live_gen B%d ", block->block_id()); print_bitmap(block->live_gen()));
a61af66fc99e Initial load
duke
parents:
diff changeset
736 TRACE_LINEAR_SCAN(4, tty->print("live_kill B%d ", block->block_id()); print_bitmap(block->live_kill()));
a61af66fc99e Initial load
duke
parents:
diff changeset
737 } // end of block iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
738
a61af66fc99e Initial load
duke
parents:
diff changeset
739 // propagate local calculated information into LinearScan object
a61af66fc99e Initial load
duke
parents:
diff changeset
740 _has_fpu_registers = local_has_fpu_registers;
a61af66fc99e Initial load
duke
parents:
diff changeset
741 compilation()->set_has_fpu_code(local_has_fpu_registers);
a61af66fc99e Initial load
duke
parents:
diff changeset
742
a61af66fc99e Initial load
duke
parents:
diff changeset
743 _num_calls = local_num_calls;
a61af66fc99e Initial load
duke
parents:
diff changeset
744 _interval_in_loop = local_interval_in_loop;
a61af66fc99e Initial load
duke
parents:
diff changeset
745 }
a61af66fc99e Initial load
duke
parents:
diff changeset
746
a61af66fc99e Initial load
duke
parents:
diff changeset
747
a61af66fc99e Initial load
duke
parents:
diff changeset
748 // ********** Phase 3: perform a backward dataflow analysis to compute global live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
749 // (sets live_in and live_out for each block)
a61af66fc99e Initial load
duke
parents:
diff changeset
750
a61af66fc99e Initial load
duke
parents:
diff changeset
751 void LinearScan::compute_global_live_sets() {
a61af66fc99e Initial load
duke
parents:
diff changeset
752 TIME_LINEAR_SCAN(timer_compute_global_live_sets);
a61af66fc99e Initial load
duke
parents:
diff changeset
753
a61af66fc99e Initial load
duke
parents:
diff changeset
754 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
755 bool change_occurred;
a61af66fc99e Initial load
duke
parents:
diff changeset
756 bool change_occurred_in_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
757 int iteration_count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
758 BitMap live_out(live_set_size()); live_out.clear(); // scratch set for calculations
a61af66fc99e Initial load
duke
parents:
diff changeset
759
a61af66fc99e Initial load
duke
parents:
diff changeset
760 // Perform a backward dataflow analysis to compute live_out and live_in for each block.
a61af66fc99e Initial load
duke
parents:
diff changeset
761 // The loop is executed until a fixpoint is reached (no changes in an iteration)
a61af66fc99e Initial load
duke
parents:
diff changeset
762 // Exception handlers must be processed because not all live values are
a61af66fc99e Initial load
duke
parents:
diff changeset
763 // present in the state array, e.g. because of global value numbering
a61af66fc99e Initial load
duke
parents:
diff changeset
764 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
765 change_occurred = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
766
a61af66fc99e Initial load
duke
parents:
diff changeset
767 // iterate all blocks in reverse order
a61af66fc99e Initial load
duke
parents:
diff changeset
768 for (int i = num_blocks - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
769 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
770
a61af66fc99e Initial load
duke
parents:
diff changeset
771 change_occurred_in_block = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
772
a61af66fc99e Initial load
duke
parents:
diff changeset
773 // live_out(block) is the union of live_in(sux), for successors sux of block
a61af66fc99e Initial load
duke
parents:
diff changeset
774 int n = block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
775 int e = block->number_of_exception_handlers();
a61af66fc99e Initial load
duke
parents:
diff changeset
776 if (n + e > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
777 // block has successors
a61af66fc99e Initial load
duke
parents:
diff changeset
778 if (n > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
779 live_out.set_from(block->sux_at(0)->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
780 for (int j = 1; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
781 live_out.set_union(block->sux_at(j)->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
782 }
a61af66fc99e Initial load
duke
parents:
diff changeset
783 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
784 live_out.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
785 }
a61af66fc99e Initial load
duke
parents:
diff changeset
786 for (int j = 0; j < e; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
787 live_out.set_union(block->exception_handler_at(j)->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
788 }
a61af66fc99e Initial load
duke
parents:
diff changeset
789
a61af66fc99e Initial load
duke
parents:
diff changeset
790 if (!block->live_out().is_same(live_out)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
791 // A change occurred. Swap the old and new live out sets to avoid copying.
a61af66fc99e Initial load
duke
parents:
diff changeset
792 BitMap temp = block->live_out();
a61af66fc99e Initial load
duke
parents:
diff changeset
793 block->set_live_out(live_out);
a61af66fc99e Initial load
duke
parents:
diff changeset
794 live_out = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
795
a61af66fc99e Initial load
duke
parents:
diff changeset
796 change_occurred = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
797 change_occurred_in_block = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
798 }
a61af66fc99e Initial load
duke
parents:
diff changeset
799 }
a61af66fc99e Initial load
duke
parents:
diff changeset
800
a61af66fc99e Initial load
duke
parents:
diff changeset
801 if (iteration_count == 0 || change_occurred_in_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
802 // live_in(block) is the union of live_gen(block) with (live_out(block) & !live_kill(block))
a61af66fc99e Initial load
duke
parents:
diff changeset
803 // note: live_in has to be computed only in first iteration or if live_out has changed!
a61af66fc99e Initial load
duke
parents:
diff changeset
804 BitMap live_in = block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
805 live_in.set_from(block->live_out());
a61af66fc99e Initial load
duke
parents:
diff changeset
806 live_in.set_difference(block->live_kill());
a61af66fc99e Initial load
duke
parents:
diff changeset
807 live_in.set_union(block->live_gen());
a61af66fc99e Initial load
duke
parents:
diff changeset
808 }
a61af66fc99e Initial load
duke
parents:
diff changeset
809
a61af66fc99e Initial load
duke
parents:
diff changeset
810 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
811 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
812 char c = ' ';
a61af66fc99e Initial load
duke
parents:
diff changeset
813 if (iteration_count == 0 || change_occurred_in_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
814 c = '*';
a61af66fc99e Initial load
duke
parents:
diff changeset
815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
816 tty->print("(%d) live_in%c B%d ", iteration_count, c, block->block_id()); print_bitmap(block->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
817 tty->print("(%d) live_out%c B%d ", iteration_count, c, block->block_id()); print_bitmap(block->live_out());
a61af66fc99e Initial load
duke
parents:
diff changeset
818 }
a61af66fc99e Initial load
duke
parents:
diff changeset
819 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
820 }
a61af66fc99e Initial load
duke
parents:
diff changeset
821 iteration_count++;
a61af66fc99e Initial load
duke
parents:
diff changeset
822
a61af66fc99e Initial load
duke
parents:
diff changeset
823 if (change_occurred && iteration_count > 50) {
a61af66fc99e Initial load
duke
parents:
diff changeset
824 BAILOUT("too many iterations in compute_global_live_sets");
a61af66fc99e Initial load
duke
parents:
diff changeset
825 }
a61af66fc99e Initial load
duke
parents:
diff changeset
826 } while (change_occurred);
a61af66fc99e Initial load
duke
parents:
diff changeset
827
a61af66fc99e Initial load
duke
parents:
diff changeset
828
a61af66fc99e Initial load
duke
parents:
diff changeset
829 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
830 // check that fixed intervals are not live at block boundaries
a61af66fc99e Initial load
duke
parents:
diff changeset
831 // (live set must be empty at fixed intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
832 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
833 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
834 for (int j = 0; j < LIR_OprDesc::vreg_base; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
835 assert(block->live_in().at(j) == false, "live_in set of fixed register must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
836 assert(block->live_out().at(j) == false, "live_out set of fixed register must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
837 assert(block->live_gen().at(j) == false, "live_gen set of fixed register must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
838 }
a61af66fc99e Initial load
duke
parents:
diff changeset
839 }
a61af66fc99e Initial load
duke
parents:
diff changeset
840 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
841
a61af66fc99e Initial load
duke
parents:
diff changeset
842 // check that the live_in set of the first block is empty
a61af66fc99e Initial load
duke
parents:
diff changeset
843 BitMap live_in_args(ir()->start()->live_in().size());
a61af66fc99e Initial load
duke
parents:
diff changeset
844 live_in_args.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
845 if (!ir()->start()->live_in().is_same(live_in_args)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
846 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
847 tty->print_cr("Error: live_in set of first block must be empty (when this fails, virtual registers are used before they are defined)");
a61af66fc99e Initial load
duke
parents:
diff changeset
848 tty->print_cr("affected registers:");
a61af66fc99e Initial load
duke
parents:
diff changeset
849 print_bitmap(ir()->start()->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
850
a61af66fc99e Initial load
duke
parents:
diff changeset
851 // print some additional information to simplify debugging
a61af66fc99e Initial load
duke
parents:
diff changeset
852 for (unsigned int i = 0; i < ir()->start()->live_in().size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
853 if (ir()->start()->live_in().at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
854 Instruction* instr = gen()->instruction_for_vreg(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
855 tty->print_cr("* vreg %d (HIR instruction %c%d)", i, instr == NULL ? ' ' : instr->type()->tchar(), instr == NULL ? 0 : instr->id());
a61af66fc99e Initial load
duke
parents:
diff changeset
856
a61af66fc99e Initial load
duke
parents:
diff changeset
857 for (int j = 0; j < num_blocks; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
858 BlockBegin* block = block_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
859 if (block->live_gen().at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
860 tty->print_cr(" used in block B%d", block->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
861 }
a61af66fc99e Initial load
duke
parents:
diff changeset
862 if (block->live_kill().at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
863 tty->print_cr(" defined in block B%d", block->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
864 }
a61af66fc99e Initial load
duke
parents:
diff changeset
865 }
a61af66fc99e Initial load
duke
parents:
diff changeset
866 }
a61af66fc99e Initial load
duke
parents:
diff changeset
867 }
a61af66fc99e Initial load
duke
parents:
diff changeset
868
a61af66fc99e Initial load
duke
parents:
diff changeset
869 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
870 // when this fails, virtual registers are used before they are defined.
a61af66fc99e Initial load
duke
parents:
diff changeset
871 assert(false, "live_in set of first block must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
872 // bailout of if this occurs in product mode.
a61af66fc99e Initial load
duke
parents:
diff changeset
873 bailout("live_in set of first block not empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
874 }
a61af66fc99e Initial load
duke
parents:
diff changeset
875 }
a61af66fc99e Initial load
duke
parents:
diff changeset
876
a61af66fc99e Initial load
duke
parents:
diff changeset
877
a61af66fc99e Initial load
duke
parents:
diff changeset
878 // ********** Phase 4: build intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
879 // (fills the list _intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
880
a61af66fc99e Initial load
duke
parents:
diff changeset
881 void LinearScan::add_use(Value value, int from, int to, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
882 assert(!value->type()->is_illegal(), "if this value is used by the interpreter it shouldn't be of indeterminate type");
a61af66fc99e Initial load
duke
parents:
diff changeset
883 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
884 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
885
a61af66fc99e Initial load
duke
parents:
diff changeset
886 if ((con == NULL || con->is_pinned()) && opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
887 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
888 add_use(opr, from, to, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
889 }
a61af66fc99e Initial load
duke
parents:
diff changeset
890 }
a61af66fc99e Initial load
duke
parents:
diff changeset
891
a61af66fc99e Initial load
duke
parents:
diff changeset
892
a61af66fc99e Initial load
duke
parents:
diff changeset
893 void LinearScan::add_def(LIR_Opr opr, int def_pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
894 TRACE_LINEAR_SCAN(2, tty->print(" def "); opr->print(tty); tty->print_cr(" def_pos %d (%d)", def_pos, use_kind));
a61af66fc99e Initial load
duke
parents:
diff changeset
895 assert(opr->is_register(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
896
a61af66fc99e Initial load
duke
parents:
diff changeset
897 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
898 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
899 add_def(opr->vreg_number(), def_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
900
a61af66fc99e Initial load
duke
parents:
diff changeset
901 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
902 int reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
903 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
904 add_def(reg, def_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
905 }
a61af66fc99e Initial load
duke
parents:
diff changeset
906 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
907 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
908 add_def(reg, def_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
909 }
a61af66fc99e Initial load
duke
parents:
diff changeset
910 }
a61af66fc99e Initial load
duke
parents:
diff changeset
911 }
a61af66fc99e Initial load
duke
parents:
diff changeset
912
a61af66fc99e Initial load
duke
parents:
diff changeset
913 void LinearScan::add_use(LIR_Opr opr, int from, int to, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
914 TRACE_LINEAR_SCAN(2, tty->print(" use "); opr->print(tty); tty->print_cr(" from %d to %d (%d)", from, to, use_kind));
a61af66fc99e Initial load
duke
parents:
diff changeset
915 assert(opr->is_register(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
916
a61af66fc99e Initial load
duke
parents:
diff changeset
917 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
918 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
919 add_use(opr->vreg_number(), from, to, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
920
a61af66fc99e Initial load
duke
parents:
diff changeset
921 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
922 int reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
923 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
924 add_use(reg, from, to, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
925 }
a61af66fc99e Initial load
duke
parents:
diff changeset
926 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
927 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
928 add_use(reg, from, to, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
929 }
a61af66fc99e Initial load
duke
parents:
diff changeset
930 }
a61af66fc99e Initial load
duke
parents:
diff changeset
931 }
a61af66fc99e Initial load
duke
parents:
diff changeset
932
a61af66fc99e Initial load
duke
parents:
diff changeset
933 void LinearScan::add_temp(LIR_Opr opr, int temp_pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
934 TRACE_LINEAR_SCAN(2, tty->print(" temp "); opr->print(tty); tty->print_cr(" temp_pos %d (%d)", temp_pos, use_kind));
a61af66fc99e Initial load
duke
parents:
diff changeset
935 assert(opr->is_register(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
936
a61af66fc99e Initial load
duke
parents:
diff changeset
937 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
938 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
939 add_temp(opr->vreg_number(), temp_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
940
a61af66fc99e Initial load
duke
parents:
diff changeset
941 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
942 int reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
943 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
944 add_temp(reg, temp_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
945 }
a61af66fc99e Initial load
duke
parents:
diff changeset
946 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
947 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
948 add_temp(reg, temp_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
949 }
a61af66fc99e Initial load
duke
parents:
diff changeset
950 }
a61af66fc99e Initial load
duke
parents:
diff changeset
951 }
a61af66fc99e Initial load
duke
parents:
diff changeset
952
a61af66fc99e Initial load
duke
parents:
diff changeset
953
a61af66fc99e Initial load
duke
parents:
diff changeset
954 void LinearScan::add_def(int reg_num, int def_pos, IntervalUseKind use_kind, BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
955 Interval* interval = interval_at(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
956 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
957 assert(interval->reg_num() == reg_num, "wrong interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
958
a61af66fc99e Initial load
duke
parents:
diff changeset
959 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
960 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
961 }
a61af66fc99e Initial load
duke
parents:
diff changeset
962
a61af66fc99e Initial load
duke
parents:
diff changeset
963 Range* r = interval->first();
a61af66fc99e Initial load
duke
parents:
diff changeset
964 if (r->from() <= def_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
965 // Update the starting point (when a range is first created for a use, its
a61af66fc99e Initial load
duke
parents:
diff changeset
966 // start is the beginning of the current block until a def is encountered.)
a61af66fc99e Initial load
duke
parents:
diff changeset
967 r->set_from(def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
968 interval->add_use_pos(def_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
969
a61af66fc99e Initial load
duke
parents:
diff changeset
970 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
971 // Dead value - make vacuous interval
a61af66fc99e Initial load
duke
parents:
diff changeset
972 // also add use_kind for dead intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
973 interval->add_range(def_pos, def_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
974 interval->add_use_pos(def_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
975 TRACE_LINEAR_SCAN(2, tty->print_cr("Warning: def of reg %d at %d occurs without use", reg_num, def_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
976 }
a61af66fc99e Initial load
duke
parents:
diff changeset
977
a61af66fc99e Initial load
duke
parents:
diff changeset
978 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
979 // Dead value - make vacuous interval
a61af66fc99e Initial load
duke
parents:
diff changeset
980 // also add use_kind for dead intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
981 interval = create_interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
982 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
983 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
984 }
a61af66fc99e Initial load
duke
parents:
diff changeset
985
a61af66fc99e Initial load
duke
parents:
diff changeset
986 interval->add_range(def_pos, def_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
987 interval->add_use_pos(def_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
988 TRACE_LINEAR_SCAN(2, tty->print_cr("Warning: dead value %d at %d in live intervals", reg_num, def_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
989 }
a61af66fc99e Initial load
duke
parents:
diff changeset
990
a61af66fc99e Initial load
duke
parents:
diff changeset
991 change_spill_definition_pos(interval, def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
992 if (use_kind == noUse && interval->spill_state() <= startInMemory) {
a61af66fc99e Initial load
duke
parents:
diff changeset
993 // detection of method-parameters and roundfp-results
a61af66fc99e Initial load
duke
parents:
diff changeset
994 // TODO: move this directly to position where use-kind is computed
a61af66fc99e Initial load
duke
parents:
diff changeset
995 interval->set_spill_state(startInMemory);
a61af66fc99e Initial load
duke
parents:
diff changeset
996 }
a61af66fc99e Initial load
duke
parents:
diff changeset
997 }
a61af66fc99e Initial load
duke
parents:
diff changeset
998
a61af66fc99e Initial load
duke
parents:
diff changeset
999 void LinearScan::add_use(int reg_num, int from, int to, IntervalUseKind use_kind, BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1000 Interval* interval = interval_at(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 if (interval == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1002 interval = create_interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1003 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1004 assert(interval->reg_num() == reg_num, "wrong interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1005
a61af66fc99e Initial load
duke
parents:
diff changeset
1006 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
1008 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1009
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 interval->add_range(from, to);
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 interval->add_use_pos(to, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
1012 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1013
a61af66fc99e Initial load
duke
parents:
diff changeset
1014 void LinearScan::add_temp(int reg_num, int temp_pos, IntervalUseKind use_kind, BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1015 Interval* interval = interval_at(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 if (interval == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1017 interval = create_interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1018 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 assert(interval->reg_num() == reg_num, "wrong interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1020
a61af66fc99e Initial load
duke
parents:
diff changeset
1021 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1022 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
1023 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1024
a61af66fc99e Initial load
duke
parents:
diff changeset
1025 interval->add_range(temp_pos, temp_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1026 interval->add_use_pos(temp_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
1027 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1028
a61af66fc99e Initial load
duke
parents:
diff changeset
1029
a61af66fc99e Initial load
duke
parents:
diff changeset
1030 // the results of this functions are used for optimizing spilling and reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
1031 // if the functions return shouldHaveRegister and the interval is spilled,
a61af66fc99e Initial load
duke
parents:
diff changeset
1032 // it is not reloaded to a register.
a61af66fc99e Initial load
duke
parents:
diff changeset
1033 IntervalUseKind LinearScan::use_kind_of_output_operand(LIR_Op* op, LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1034 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1035 assert(op->as_Op1() != NULL, "lir_move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1036 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1037 LIR_Opr res = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1038 bool result_in_memory = res->is_virtual() && gen()->is_vreg_flag_set(res->vreg_number(), LIRGenerator::must_start_in_memory);
a61af66fc99e Initial load
duke
parents:
diff changeset
1039
a61af66fc99e Initial load
duke
parents:
diff changeset
1040 if (result_in_memory) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1041 // Begin of an interval with must_start_in_memory set.
a61af66fc99e Initial load
duke
parents:
diff changeset
1042 // This interval will always get a stack slot first, so return noUse.
a61af66fc99e Initial load
duke
parents:
diff changeset
1043 return noUse;
a61af66fc99e Initial load
duke
parents:
diff changeset
1044
a61af66fc99e Initial load
duke
parents:
diff changeset
1045 } else if (move->in_opr()->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1046 // method argument (condition must be equal to handle_method_arguments)
a61af66fc99e Initial load
duke
parents:
diff changeset
1047 return noUse;
a61af66fc99e Initial load
duke
parents:
diff changeset
1048
a61af66fc99e Initial load
duke
parents:
diff changeset
1049 } else if (move->in_opr()->is_register() && move->result_opr()->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1050 // Move from register to register
a61af66fc99e Initial load
duke
parents:
diff changeset
1051 if (block_of_op_with_id(op->id())->is_set(BlockBegin::osr_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1052 // special handling of phi-function moves inside osr-entry blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1053 // input operand must have a register instead of output operand (leads to better register allocation)
a61af66fc99e Initial load
duke
parents:
diff changeset
1054 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1055 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1056 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1057 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1058
a61af66fc99e Initial load
duke
parents:
diff changeset
1059 if (opr->is_virtual() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1060 gen()->is_vreg_flag_set(opr->vreg_number(), LIRGenerator::must_start_in_memory)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1061 // result is a stack-slot, so prevent immediate reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
1062 return noUse;
a61af66fc99e Initial load
duke
parents:
diff changeset
1063 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1064
a61af66fc99e Initial load
duke
parents:
diff changeset
1065 // all other operands require a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1066 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1067 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1068
a61af66fc99e Initial load
duke
parents:
diff changeset
1069 IntervalUseKind LinearScan::use_kind_of_input_operand(LIR_Op* op, LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1070 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1071 assert(op->as_Op1() != NULL, "lir_move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1072 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1073 LIR_Opr res = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1074 bool result_in_memory = res->is_virtual() && gen()->is_vreg_flag_set(res->vreg_number(), LIRGenerator::must_start_in_memory);
a61af66fc99e Initial load
duke
parents:
diff changeset
1075
a61af66fc99e Initial load
duke
parents:
diff changeset
1076 if (result_in_memory) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1077 // Move to an interval with must_start_in_memory set.
a61af66fc99e Initial load
duke
parents:
diff changeset
1078 // To avoid moves from stack to stack (not allowed) force the input operand to a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1079 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1080
a61af66fc99e Initial load
duke
parents:
diff changeset
1081 } else if (move->in_opr()->is_register() && move->result_opr()->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1082 // Move from register to register
a61af66fc99e Initial load
duke
parents:
diff changeset
1083 if (block_of_op_with_id(op->id())->is_set(BlockBegin::osr_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1084 // special handling of phi-function moves inside osr-entry blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1085 // input operand must have a register instead of output operand (leads to better register allocation)
a61af66fc99e Initial load
duke
parents:
diff changeset
1086 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1087 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1088
a61af66fc99e Initial load
duke
parents:
diff changeset
1089 // The input operand is not forced to a register (moves from stack to register are allowed),
a61af66fc99e Initial load
duke
parents:
diff changeset
1090 // but it is faster if the input operand is in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1091 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1092 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1093 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1094
a61af66fc99e Initial load
duke
parents:
diff changeset
1095
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1096 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1097 if (op->code() == lir_cmove) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1098 // conditional moves can handle stack operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1099 assert(op->result_opr()->is_register(), "result must always be in a register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1100 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1102
a61af66fc99e Initial load
duke
parents:
diff changeset
1103 // optimizations for second input operand of arithmehtic operations on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
1104 // this operand is allowed to be on the stack in some cases
a61af66fc99e Initial load
duke
parents:
diff changeset
1105 BasicType opr_type = opr->type_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
1106 if (opr_type == T_FLOAT || opr_type == T_DOUBLE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1107 if ((UseSSE == 1 && opr_type == T_FLOAT) || UseSSE >= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1108 // SSE float instruction (T_DOUBLE only supported with SSE2)
a61af66fc99e Initial load
duke
parents:
diff changeset
1109 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1110 case lir_cmp:
a61af66fc99e Initial load
duke
parents:
diff changeset
1111 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
1112 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1113 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
1114 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
1115 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1116 assert(op->as_Op2() != NULL, "must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1117 LIR_Op2* op2 = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1118 if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1119 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");
a61af66fc99e Initial load
duke
parents:
diff changeset
1120 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1121 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1122 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1123 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1124 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1125 // FPU stack float instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
1126 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1127 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
1128 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1129 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
1130 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
1131 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1132 assert(op->as_Op2() != NULL, "must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1133 LIR_Op2* op2 = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1134 if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1135 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");
a61af66fc99e Initial load
duke
parents:
diff changeset
1136 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1137 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1140 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1141
a61af66fc99e Initial load
duke
parents:
diff changeset
1142 } else if (opr_type != T_LONG) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1143 // integer instruction (note: long operands must always be in register)
a61af66fc99e Initial load
duke
parents:
diff changeset
1144 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1145 case lir_cmp:
a61af66fc99e Initial load
duke
parents:
diff changeset
1146 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
1147 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1148 case lir_logic_and:
a61af66fc99e Initial load
duke
parents:
diff changeset
1149 case lir_logic_or:
a61af66fc99e Initial load
duke
parents:
diff changeset
1150 case lir_logic_xor:
a61af66fc99e Initial load
duke
parents:
diff changeset
1151 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1152 assert(op->as_Op2() != NULL, "must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1153 LIR_Op2* op2 = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1154 if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1155 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");
a61af66fc99e Initial load
duke
parents:
diff changeset
1156 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1157 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1158 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1159 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1160 }
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1161 #endif // X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1162
a61af66fc99e Initial load
duke
parents:
diff changeset
1163 // all other operands require a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1164 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1165 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1166
a61af66fc99e Initial load
duke
parents:
diff changeset
1167
a61af66fc99e Initial load
duke
parents:
diff changeset
1168 void LinearScan::handle_method_arguments(LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1169 // special handling for method arguments (moves from stack to virtual register):
a61af66fc99e Initial load
duke
parents:
diff changeset
1170 // the interval gets no register assigned, but the stack slot.
a61af66fc99e Initial load
duke
parents:
diff changeset
1171 // it is split before the first use by the register allocator.
a61af66fc99e Initial load
duke
parents:
diff changeset
1172
a61af66fc99e Initial load
duke
parents:
diff changeset
1173 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1174 assert(op->as_Op1() != NULL, "must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1175 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1176
a61af66fc99e Initial load
duke
parents:
diff changeset
1177 if (move->in_opr()->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1178 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1179 int arg_size = compilation()->method()->arg_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1180 LIR_Opr o = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1181 if (o->is_single_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1182 assert(o->single_stack_ix() >= 0 && o->single_stack_ix() < arg_size, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
1183 } else if (o->is_double_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1184 assert(o->double_stack_ix() >= 0 && o->double_stack_ix() < arg_size, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
1185 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1186 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
1187 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1188
a61af66fc99e Initial load
duke
parents:
diff changeset
1189 assert(move->id() > 0, "invalid id");
a61af66fc99e Initial load
duke
parents:
diff changeset
1190 assert(block_of_op_with_id(move->id())->number_of_preds() == 0, "move from stack must be in first block");
a61af66fc99e Initial load
duke
parents:
diff changeset
1191 assert(move->result_opr()->is_virtual(), "result of move must be a virtual register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1192
a61af66fc99e Initial load
duke
parents:
diff changeset
1193 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())));
a61af66fc99e Initial load
duke
parents:
diff changeset
1194 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1195
a61af66fc99e Initial load
duke
parents:
diff changeset
1196 Interval* interval = interval_at(reg_num(move->result_opr()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1197
a61af66fc99e Initial load
duke
parents:
diff changeset
1198 int stack_slot = LinearScan::nof_regs + (move->in_opr()->is_single_stack() ? move->in_opr()->single_stack_ix() : move->in_opr()->double_stack_ix());
a61af66fc99e Initial load
duke
parents:
diff changeset
1199 interval->set_canonical_spill_slot(stack_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
1200 interval->assign_reg(stack_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
1201 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1204
a61af66fc99e Initial load
duke
parents:
diff changeset
1205 void LinearScan::handle_doubleword_moves(LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1206 // special handling for doubleword move from memory to register:
a61af66fc99e Initial load
duke
parents:
diff changeset
1207 // in this case the registers of the input address and the result
a61af66fc99e Initial load
duke
parents:
diff changeset
1208 // registers must not overlap -> add a temp range for the input registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1209 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1210 assert(op->as_Op1() != NULL, "must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1211 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1212
a61af66fc99e Initial load
duke
parents:
diff changeset
1213 if (move->result_opr()->is_double_cpu() && move->in_opr()->is_pointer()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1214 LIR_Address* address = move->in_opr()->as_address_ptr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1215 if (address != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1216 if (address->base()->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1217 add_temp(address->base(), op->id(), noUse);
a61af66fc99e Initial load
duke
parents:
diff changeset
1218 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1219 if (address->index()->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1220 add_temp(address->index(), op->id(), noUse);
a61af66fc99e Initial load
duke
parents:
diff changeset
1221 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1222 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1223 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1224 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1226
a61af66fc99e Initial load
duke
parents:
diff changeset
1227 void LinearScan::add_register_hints(LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1228 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1229 case lir_move: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
1230 case lir_convert: {
a61af66fc99e Initial load
duke
parents:
diff changeset
1231 assert(op->as_Op1() != NULL, "lir_move, lir_convert must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1232 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1233
a61af66fc99e Initial load
duke
parents:
diff changeset
1234 LIR_Opr move_from = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1235 LIR_Opr move_to = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1236
a61af66fc99e Initial load
duke
parents:
diff changeset
1237 if (move_to->is_register() && move_from->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1238 Interval* from = interval_at(reg_num(move_from));
a61af66fc99e Initial load
duke
parents:
diff changeset
1239 Interval* to = interval_at(reg_num(move_to));
a61af66fc99e Initial load
duke
parents:
diff changeset
1240 if (from != NULL && to != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1241 to->set_register_hint(from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1242 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1243 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1244 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1245 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1246 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1247 case lir_cmove: {
a61af66fc99e Initial load
duke
parents:
diff changeset
1248 assert(op->as_Op2() != NULL, "lir_cmove must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1249 LIR_Op2* cmove = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1250
a61af66fc99e Initial load
duke
parents:
diff changeset
1251 LIR_Opr move_from = cmove->in_opr1();
a61af66fc99e Initial load
duke
parents:
diff changeset
1252 LIR_Opr move_to = cmove->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1253
a61af66fc99e Initial load
duke
parents:
diff changeset
1254 if (move_to->is_register() && move_from->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1255 Interval* from = interval_at(reg_num(move_from));
a61af66fc99e Initial load
duke
parents:
diff changeset
1256 Interval* to = interval_at(reg_num(move_to));
a61af66fc99e Initial load
duke
parents:
diff changeset
1257 if (from != NULL && to != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1258 to->set_register_hint(from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1259 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1260 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1261 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1262 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1263 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1264 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1265 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1266
a61af66fc99e Initial load
duke
parents:
diff changeset
1267
a61af66fc99e Initial load
duke
parents:
diff changeset
1268 void LinearScan::build_intervals() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1269 TIME_LINEAR_SCAN(timer_build_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1270
a61af66fc99e Initial load
duke
parents:
diff changeset
1271 // initialize interval list with expected number of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1272 // (32 is added to have some space for split children without having to resize the list)
a61af66fc99e Initial load
duke
parents:
diff changeset
1273 _intervals = IntervalList(num_virtual_regs() + 32);
a61af66fc99e Initial load
duke
parents:
diff changeset
1274 // initialize all slots that are used by build_intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1275 _intervals.at_put_grow(num_virtual_regs() - 1, NULL, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1276
a61af66fc99e Initial load
duke
parents:
diff changeset
1277 // create a list with all caller-save registers (cpu, fpu, xmm)
a61af66fc99e Initial load
duke
parents:
diff changeset
1278 // when an instruction is a call, a temp range is created for all these registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1279 int num_caller_save_registers = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1280 int caller_save_registers[LinearScan::nof_regs];
a61af66fc99e Initial load
duke
parents:
diff changeset
1281
a61af66fc99e Initial load
duke
parents:
diff changeset
1282 int i;
2002
ac637b7220d1 6985015: C1 needs to support compressed oops
iveresov
parents: 1972
diff changeset
1283 for (i = 0; i < FrameMap::nof_caller_save_cpu_regs(); i++) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1284 LIR_Opr opr = FrameMap::caller_save_cpu_reg_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1285 assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1286 assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1287 caller_save_registers[num_caller_save_registers++] = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1288 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1289
a61af66fc99e Initial load
duke
parents:
diff changeset
1290 // temp ranges for fpu registers are only created when the method has
a61af66fc99e Initial load
duke
parents:
diff changeset
1291 // virtual fpu operands. Otherwise no allocation for fpu registers is
a61af66fc99e Initial load
duke
parents:
diff changeset
1292 // perfomed and so the temp ranges would be useless
a61af66fc99e Initial load
duke
parents:
diff changeset
1293 if (has_fpu_registers()) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1294 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1295 if (UseSSE < 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1296 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1297 for (i = 0; i < FrameMap::nof_caller_save_fpu_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1298 LIR_Opr opr = FrameMap::caller_save_fpu_reg_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1299 assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1300 assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1301 caller_save_registers[num_caller_save_registers++] = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1302 }
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1303 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1304 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1305 if (UseSSE > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1306 for (i = 0; i < FrameMap::nof_caller_save_xmm_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1307 LIR_Opr opr = FrameMap::caller_save_xmm_reg_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1308 assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1309 assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1310 caller_save_registers[num_caller_save_registers++] = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1311 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1312 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1313 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1314 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1315 assert(num_caller_save_registers <= LinearScan::nof_regs, "out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1316
a61af66fc99e Initial load
duke
parents:
diff changeset
1317
a61af66fc99e Initial load
duke
parents:
diff changeset
1318 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
1319
a61af66fc99e Initial load
duke
parents:
diff changeset
1320 // iterate all blocks in reverse order
a61af66fc99e Initial load
duke
parents:
diff changeset
1321 for (i = block_count() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1322 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1323 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1324 int block_from = block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1325 int block_to = block->last_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1326
a61af66fc99e Initial load
duke
parents:
diff changeset
1327 assert(block_from == instructions->at(0)->id(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
1328 assert(block_to == instructions->at(instructions->length() - 1)->id(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
1329
a61af66fc99e Initial load
duke
parents:
diff changeset
1330 // Update intervals for registers live at the end of this block;
a61af66fc99e Initial load
duke
parents:
diff changeset
1331 BitMap live = block->live_out();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1332 int size = (int)live.size();
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1333 for (int number = (int)live.get_next_one_offset(0, size); number < size; number = (int)live.get_next_one_offset(number + 1, size)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1334 assert(live.at(number), "should not stop here otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1335 assert(number >= LIR_OprDesc::vreg_base, "fixed intervals must not be live on block bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1336 TRACE_LINEAR_SCAN(2, tty->print_cr("live in %d to %d", number, block_to + 2));
a61af66fc99e Initial load
duke
parents:
diff changeset
1337
a61af66fc99e Initial load
duke
parents:
diff changeset
1338 add_use(number, block_from, block_to + 2, noUse, T_ILLEGAL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1339
a61af66fc99e Initial load
duke
parents:
diff changeset
1340 // add special use positions for loop-end blocks when the
a61af66fc99e Initial load
duke
parents:
diff changeset
1341 // interval is used anywhere inside this loop. It's possible
a61af66fc99e Initial load
duke
parents:
diff changeset
1342 // that the block was part of a non-natural loop, so it might
a61af66fc99e Initial load
duke
parents:
diff changeset
1343 // have an invalid loop index.
a61af66fc99e Initial load
duke
parents:
diff changeset
1344 if (block->is_set(BlockBegin::linear_scan_loop_end_flag) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1345 block->loop_index() != -1 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1346 is_interval_in_loop(number, block->loop_index())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1347 interval_at(number)->add_use_pos(block_to + 1, loopEndMarker);
a61af66fc99e Initial load
duke
parents:
diff changeset
1348 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1349 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1350
a61af66fc99e Initial load
duke
parents:
diff changeset
1351 // iterate all instructions of the block in reverse order.
a61af66fc99e Initial load
duke
parents:
diff changeset
1352 // skip the first instruction because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
1353 // definitions of intervals are processed before uses
a61af66fc99e Initial load
duke
parents:
diff changeset
1354 assert(visitor.no_operands(instructions->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1355 for (int j = instructions->length() - 1; j >= 1; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1356 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
1357 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1358
a61af66fc99e Initial load
duke
parents:
diff changeset
1359 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1360 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1361
a61af66fc99e Initial load
duke
parents:
diff changeset
1362 // add a temp range for each register if operation destroys caller-save registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1363 if (visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1364 for (int k = 0; k < num_caller_save_registers; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1365 add_temp(caller_save_registers[k], op_id, noUse, T_ILLEGAL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1366 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1367 TRACE_LINEAR_SCAN(4, tty->print_cr("operation destroys all caller-save registers"));
a61af66fc99e Initial load
duke
parents:
diff changeset
1368 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1369
a61af66fc99e Initial load
duke
parents:
diff changeset
1370 // Add any platform dependent temps
a61af66fc99e Initial load
duke
parents:
diff changeset
1371 pd_add_temps(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1372
a61af66fc99e Initial load
duke
parents:
diff changeset
1373 // visit definitions (output and temp operands)
a61af66fc99e Initial load
duke
parents:
diff changeset
1374 int k, n;
a61af66fc99e Initial load
duke
parents:
diff changeset
1375 n = visitor.opr_count(LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1376 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1377 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1378 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1379 add_def(opr, op_id, use_kind_of_output_operand(op, opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
1380 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1381
a61af66fc99e Initial load
duke
parents:
diff changeset
1382 n = visitor.opr_count(LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1383 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1384 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1385 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1386 add_temp(opr, op_id, mustHaveRegister);
a61af66fc99e Initial load
duke
parents:
diff changeset
1387 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1388
a61af66fc99e Initial load
duke
parents:
diff changeset
1389 // visit uses (input operands)
a61af66fc99e Initial load
duke
parents:
diff changeset
1390 n = visitor.opr_count(LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1391 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1392 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1393 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1394 add_use(opr, block_from, op_id, use_kind_of_input_operand(op, opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
1395 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1396
a61af66fc99e Initial load
duke
parents:
diff changeset
1397 // Add uses of live locals from interpreter's point of view for proper
a61af66fc99e Initial load
duke
parents:
diff changeset
1398 // debug information generation
a61af66fc99e Initial load
duke
parents:
diff changeset
1399 // Treat these operands as temp values (if the life range is extended
a61af66fc99e Initial load
duke
parents:
diff changeset
1400 // to a call site, the value would be in a register at the call otherwise)
a61af66fc99e Initial load
duke
parents:
diff changeset
1401 n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1402 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1403 CodeEmitInfo* info = visitor.info_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1404 ValueStack* stack = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
1405 for_each_state_value(stack, value,
a61af66fc99e Initial load
duke
parents:
diff changeset
1406 add_use(value, block_from, op_id + 1, noUse);
a61af66fc99e Initial load
duke
parents:
diff changeset
1407 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1408 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1409
a61af66fc99e Initial load
duke
parents:
diff changeset
1410 // special steps for some instructions (especially moves)
a61af66fc99e Initial load
duke
parents:
diff changeset
1411 handle_method_arguments(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1412 handle_doubleword_moves(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1413 add_register_hints(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1414
a61af66fc99e Initial load
duke
parents:
diff changeset
1415 } // end of instruction iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
1416 } // end of block iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
1417
a61af66fc99e Initial load
duke
parents:
diff changeset
1418
a61af66fc99e Initial load
duke
parents:
diff changeset
1419 // add the range [0, 1[ to all fixed intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1420 // -> the register allocator need not handle unhandled fixed intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1421 for (int n = 0; n < LinearScan::nof_regs; n++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1422 Interval* interval = interval_at(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
1423 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1424 interval->add_range(0, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1425 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1426 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1427 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1428
a61af66fc99e Initial load
duke
parents:
diff changeset
1429
a61af66fc99e Initial load
duke
parents:
diff changeset
1430 // ********** Phase 5: actual register allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
1431
a61af66fc99e Initial load
duke
parents:
diff changeset
1432 int LinearScan::interval_cmp(Interval** a, Interval** b) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1433 if (*a != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1434 if (*b != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1435 return (*a)->from() - (*b)->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1436 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1437 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1438 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1439 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1440 if (*b != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1441 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1442 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1443 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1444 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1445 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1446 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1447
a61af66fc99e Initial load
duke
parents:
diff changeset
1448 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1449 bool LinearScan::is_sorted(IntervalArray* intervals) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1450 int from = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1451 int i, j;
a61af66fc99e Initial load
duke
parents:
diff changeset
1452 for (i = 0; i < intervals->length(); i ++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1453 Interval* it = intervals->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1454 if (it != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1455 if (from > it->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1456 assert(false, "");
a61af66fc99e Initial load
duke
parents:
diff changeset
1457 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
1458 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1459 from = it->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1461 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1462
a61af66fc99e Initial load
duke
parents:
diff changeset
1463 // check in both directions if sorted list and unsorted list contain same intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1464 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1465 if (interval_at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1466 int num_found = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1467 for (j = 0; j < intervals->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1468 if (interval_at(i) == intervals->at(j)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1469 num_found++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1470 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1471 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1472 assert(num_found == 1, "lists do not contain same intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
1473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1474 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1475 for (j = 0; j < intervals->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1476 int num_found = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1477 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1478 if (interval_at(i) == intervals->at(j)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1479 num_found++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1481 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1482 assert(num_found == 1, "lists do not contain same intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
1483 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1484
a61af66fc99e Initial load
duke
parents:
diff changeset
1485 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1486 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1487 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1488
a61af66fc99e Initial load
duke
parents:
diff changeset
1489 void LinearScan::add_to_list(Interval** first, Interval** prev, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1490 if (*prev != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1491 (*prev)->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1492 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1493 *first = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1494 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1495 *prev = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1496 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1497
a61af66fc99e Initial load
duke
parents:
diff changeset
1498 void LinearScan::create_unhandled_lists(Interval** list1, Interval** list2, bool (is_list1)(const Interval* i), bool (is_list2)(const Interval* i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1499 assert(is_sorted(_sorted_intervals), "interval list is not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
1500
a61af66fc99e Initial load
duke
parents:
diff changeset
1501 *list1 = *list2 = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
1502
a61af66fc99e Initial load
duke
parents:
diff changeset
1503 Interval* list1_prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1504 Interval* list2_prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1505 Interval* v;
a61af66fc99e Initial load
duke
parents:
diff changeset
1506
a61af66fc99e Initial load
duke
parents:
diff changeset
1507 const int n = _sorted_intervals->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1508 for (int i = 0; i < n; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1509 v = _sorted_intervals->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1510 if (v == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
1511
a61af66fc99e Initial load
duke
parents:
diff changeset
1512 if (is_list1(v)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1513 add_to_list(list1, &list1_prev, v);
a61af66fc99e Initial load
duke
parents:
diff changeset
1514 } else if (is_list2 == NULL || is_list2(v)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1515 add_to_list(list2, &list2_prev, v);
a61af66fc99e Initial load
duke
parents:
diff changeset
1516 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1517 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1518
a61af66fc99e Initial load
duke
parents:
diff changeset
1519 if (list1_prev != NULL) list1_prev->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
1520 if (list2_prev != NULL) list2_prev->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
1521
a61af66fc99e Initial load
duke
parents:
diff changeset
1522 assert(list1_prev == NULL || list1_prev->next() == Interval::end(), "linear list ends not with sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
1523 assert(list2_prev == NULL || list2_prev->next() == Interval::end(), "linear list ends not with sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
1524 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1525
a61af66fc99e Initial load
duke
parents:
diff changeset
1526
a61af66fc99e Initial load
duke
parents:
diff changeset
1527 void LinearScan::sort_intervals_before_allocation() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1528 TIME_LINEAR_SCAN(timer_sort_intervals_before);
a61af66fc99e Initial load
duke
parents:
diff changeset
1529
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1530 if (_needs_full_resort) {
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1531 // There is no known reason why this should occur but just in case...
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1532 assert(false, "should never occur");
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1533 // Re-sort existing interval list because an Interval::from() has changed
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1534 _sorted_intervals->sort(interval_cmp);
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1535 _needs_full_resort = false;
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1536 }
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1537
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1538 IntervalList* unsorted_list = &_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1539 int unsorted_len = unsorted_list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1540 int sorted_len = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1541 int unsorted_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
1542 int sorted_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1543 int sorted_from_max = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1544
a61af66fc99e Initial load
duke
parents:
diff changeset
1545 // calc number of items for sorted list (sorted list must not contain NULL values)
a61af66fc99e Initial load
duke
parents:
diff changeset
1546 for (unsorted_idx = 0; unsorted_idx < unsorted_len; unsorted_idx++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1547 if (unsorted_list->at(unsorted_idx) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1548 sorted_len++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1549 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1550 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1551 IntervalArray* sorted_list = new IntervalArray(sorted_len);
a61af66fc99e Initial load
duke
parents:
diff changeset
1552
a61af66fc99e Initial load
duke
parents:
diff changeset
1553 // special sorting algorithm: the original interval-list is almost sorted,
a61af66fc99e Initial load
duke
parents:
diff changeset
1554 // only some intervals are swapped. So this is much faster than a complete QuickSort
a61af66fc99e Initial load
duke
parents:
diff changeset
1555 for (unsorted_idx = 0; unsorted_idx < unsorted_len; unsorted_idx++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1556 Interval* cur_interval = unsorted_list->at(unsorted_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
1557
a61af66fc99e Initial load
duke
parents:
diff changeset
1558 if (cur_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1559 int cur_from = cur_interval->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1560
a61af66fc99e Initial load
duke
parents:
diff changeset
1561 if (sorted_from_max <= cur_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1562 sorted_list->at_put(sorted_idx++, cur_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1563 sorted_from_max = cur_interval->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1564 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1565 // the asumption that the intervals are already sorted failed,
a61af66fc99e Initial load
duke
parents:
diff changeset
1566 // so this interval must be sorted in manually
a61af66fc99e Initial load
duke
parents:
diff changeset
1567 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
1568 for (j = sorted_idx - 1; j >= 0 && cur_from < sorted_list->at(j)->from(); j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1569 sorted_list->at_put(j + 1, sorted_list->at(j));
a61af66fc99e Initial load
duke
parents:
diff changeset
1570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1571 sorted_list->at_put(j + 1, cur_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1572 sorted_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1573 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1574 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1575 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1576 _sorted_intervals = sorted_list;
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1577 assert(is_sorted(_sorted_intervals), "intervals unsorted");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1578 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1579
a61af66fc99e Initial load
duke
parents:
diff changeset
1580 void LinearScan::sort_intervals_after_allocation() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1581 TIME_LINEAR_SCAN(timer_sort_intervals_after);
a61af66fc99e Initial load
duke
parents:
diff changeset
1582
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1583 if (_needs_full_resort) {
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1584 // Re-sort existing interval list because an Interval::from() has changed
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1585 _sorted_intervals->sort(interval_cmp);
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1586 _needs_full_resort = false;
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1587 }
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1588
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1589 IntervalArray* old_list = _sorted_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1590 IntervalList* new_list = _new_intervals_from_allocation;
a61af66fc99e Initial load
duke
parents:
diff changeset
1591 int old_len = old_list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1592 int new_len = new_list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1593
a61af66fc99e Initial load
duke
parents:
diff changeset
1594 if (new_len == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1595 // no intervals have been added during allocation, so sorted list is already up to date
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1596 assert(is_sorted(_sorted_intervals), "intervals unsorted");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1597 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1598 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1599
a61af66fc99e Initial load
duke
parents:
diff changeset
1600 // conventional sort-algorithm for new intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1601 new_list->sort(interval_cmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
1602
a61af66fc99e Initial load
duke
parents:
diff changeset
1603 // merge old and new list (both already sorted) into one combined list
a61af66fc99e Initial load
duke
parents:
diff changeset
1604 IntervalArray* combined_list = new IntervalArray(old_len + new_len);
a61af66fc99e Initial load
duke
parents:
diff changeset
1605 int old_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1606 int new_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1607
a61af66fc99e Initial load
duke
parents:
diff changeset
1608 while (old_idx + new_idx < old_len + new_len) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1609 if (new_idx >= new_len || (old_idx < old_len && old_list->at(old_idx)->from() <= new_list->at(new_idx)->from())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1610 combined_list->at_put(old_idx + new_idx, old_list->at(old_idx));
a61af66fc99e Initial load
duke
parents:
diff changeset
1611 old_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1612 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1613 combined_list->at_put(old_idx + new_idx, new_list->at(new_idx));
a61af66fc99e Initial load
duke
parents:
diff changeset
1614 new_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1615 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1616 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1617
a61af66fc99e Initial load
duke
parents:
diff changeset
1618 _sorted_intervals = combined_list;
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1619 assert(is_sorted(_sorted_intervals), "intervals unsorted");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1620 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1621
a61af66fc99e Initial load
duke
parents:
diff changeset
1622
a61af66fc99e Initial load
duke
parents:
diff changeset
1623 void LinearScan::allocate_registers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1624 TIME_LINEAR_SCAN(timer_allocate_registers);
a61af66fc99e Initial load
duke
parents:
diff changeset
1625
a61af66fc99e Initial load
duke
parents:
diff changeset
1626 Interval* precolored_cpu_intervals, *not_precolored_cpu_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1627 Interval* precolored_fpu_intervals, *not_precolored_fpu_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1628
a61af66fc99e Initial load
duke
parents:
diff changeset
1629 create_unhandled_lists(&precolored_cpu_intervals, &not_precolored_cpu_intervals, is_precolored_cpu_interval, is_virtual_cpu_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1630 if (has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1631 create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1632 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1633 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1634 // fpu register allocation is omitted because no virtual fpu registers are present
a61af66fc99e Initial load
duke
parents:
diff changeset
1635 // just check this again...
a61af66fc99e Initial load
duke
parents:
diff changeset
1636 create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1637 assert(not_precolored_fpu_intervals == Interval::end(), "missed an uncolored fpu interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1638 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1639 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1640
a61af66fc99e Initial load
duke
parents:
diff changeset
1641 // allocate cpu registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1642 LinearScanWalker cpu_lsw(this, precolored_cpu_intervals, not_precolored_cpu_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1643 cpu_lsw.walk();
a61af66fc99e Initial load
duke
parents:
diff changeset
1644 cpu_lsw.finish_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
1645
a61af66fc99e Initial load
duke
parents:
diff changeset
1646 if (has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1647 // allocate fpu registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1648 LinearScanWalker fpu_lsw(this, precolored_fpu_intervals, not_precolored_fpu_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1649 fpu_lsw.walk();
a61af66fc99e Initial load
duke
parents:
diff changeset
1650 fpu_lsw.finish_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
1651 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1652 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1653
a61af66fc99e Initial load
duke
parents:
diff changeset
1654
a61af66fc99e Initial load
duke
parents:
diff changeset
1655 // ********** Phase 6: resolve data flow
a61af66fc99e Initial load
duke
parents:
diff changeset
1656 // (insert moves at edges between blocks if intervals have been split)
a61af66fc99e Initial load
duke
parents:
diff changeset
1657
a61af66fc99e Initial load
duke
parents:
diff changeset
1658 // wrapper for Interval::split_child_at_op_id that performs a bailout in product mode
a61af66fc99e Initial load
duke
parents:
diff changeset
1659 // instead of returning NULL
a61af66fc99e Initial load
duke
parents:
diff changeset
1660 Interval* LinearScan::split_child_at_op_id(Interval* interval, int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1661 Interval* result = interval->split_child_at_op_id(op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1662 if (result != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1663 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
1664 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1665
a61af66fc99e Initial load
duke
parents:
diff changeset
1666 assert(false, "must find an interval, but do a clean bailout in product mode");
a61af66fc99e Initial load
duke
parents:
diff changeset
1667 result = new Interval(LIR_OprDesc::vreg_base);
a61af66fc99e Initial load
duke
parents:
diff changeset
1668 result->assign_reg(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1669 result->set_type(T_INT);
a61af66fc99e Initial load
duke
parents:
diff changeset
1670 BAILOUT_("LinearScan: interval is NULL", result);
a61af66fc99e Initial load
duke
parents:
diff changeset
1671 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1672
a61af66fc99e Initial load
duke
parents:
diff changeset
1673
a61af66fc99e Initial load
duke
parents:
diff changeset
1674 Interval* LinearScan::interval_at_block_begin(BlockBegin* block, int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1675 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1676 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1677
a61af66fc99e Initial load
duke
parents:
diff changeset
1678 return split_child_at_op_id(interval_at(reg_num), block->first_lir_instruction_id(), LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1679 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1680
a61af66fc99e Initial load
duke
parents:
diff changeset
1681 Interval* LinearScan::interval_at_block_end(BlockBegin* block, int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1682 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1683 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1684
a61af66fc99e Initial load
duke
parents:
diff changeset
1685 return split_child_at_op_id(interval_at(reg_num), block->last_lir_instruction_id() + 1, LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1686 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1687
a61af66fc99e Initial load
duke
parents:
diff changeset
1688 Interval* LinearScan::interval_at_op_id(int reg_num, int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1689 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1690 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1691
a61af66fc99e Initial load
duke
parents:
diff changeset
1692 return split_child_at_op_id(interval_at(reg_num), op_id, LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1693 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1694
a61af66fc99e Initial load
duke
parents:
diff changeset
1695
a61af66fc99e Initial load
duke
parents:
diff changeset
1696 void LinearScan::resolve_collect_mappings(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1697 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1698
a61af66fc99e Initial load
duke
parents:
diff changeset
1699 const int num_regs = num_virtual_regs();
a61af66fc99e Initial load
duke
parents:
diff changeset
1700 const int size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1701 const BitMap live_at_edge = to_block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
1702
a61af66fc99e Initial load
duke
parents:
diff changeset
1703 // visit all registers where the live_at_edge bit is set
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1704 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)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1705 assert(r < num_regs, "live information set for not exisiting interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1706 assert(from_block->live_out().at(r) && to_block->live_in().at(r), "interval not live at this edge");
a61af66fc99e Initial load
duke
parents:
diff changeset
1707
a61af66fc99e Initial load
duke
parents:
diff changeset
1708 Interval* from_interval = interval_at_block_end(from_block, r);
a61af66fc99e Initial load
duke
parents:
diff changeset
1709 Interval* to_interval = interval_at_block_begin(to_block, r);
a61af66fc99e Initial load
duke
parents:
diff changeset
1710
a61af66fc99e Initial load
duke
parents:
diff changeset
1711 if (from_interval != to_interval && (from_interval->assigned_reg() != to_interval->assigned_reg() || from_interval->assigned_regHi() != to_interval->assigned_regHi())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1712 // need to insert move instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
1713 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1714 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1715 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1716 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1717
a61af66fc99e Initial load
duke
parents:
diff changeset
1718
a61af66fc99e Initial load
duke
parents:
diff changeset
1719 void LinearScan::resolve_find_insert_pos(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1720 if (from_block->number_of_sux() <= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1721 TRACE_LINEAR_SCAN(4, tty->print_cr("inserting moves at end of from_block B%d", from_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1722
a61af66fc99e Initial load
duke
parents:
diff changeset
1723 LIR_OpList* instructions = from_block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1724 LIR_OpBranch* branch = instructions->last()->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
1725 if (branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1726 // insert moves before branch
a61af66fc99e Initial load
duke
parents:
diff changeset
1727 assert(branch->cond() == lir_cond_always, "block does not end with an unconditional jump");
a61af66fc99e Initial load
duke
parents:
diff changeset
1728 move_resolver.set_insert_position(from_block->lir(), instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1729 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1730 move_resolver.set_insert_position(from_block->lir(), instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1731 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1732
a61af66fc99e Initial load
duke
parents:
diff changeset
1733 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1734 TRACE_LINEAR_SCAN(4, tty->print_cr("inserting moves at beginning of to_block B%d", to_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1735 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1736 assert(from_block->lir()->instructions_list()->at(0)->as_OpLabel() != NULL, "block does not start with a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1737
a61af66fc99e Initial load
duke
parents:
diff changeset
1738 // because the number of predecessor edges matches the number of
a61af66fc99e Initial load
duke
parents:
diff changeset
1739 // successor edges, blocks which are reached by switch statements
a61af66fc99e Initial load
duke
parents:
diff changeset
1740 // may have be more than one predecessor but it will be guaranteed
a61af66fc99e Initial load
duke
parents:
diff changeset
1741 // that all predecessors will be the same.
a61af66fc99e Initial load
duke
parents:
diff changeset
1742 for (int i = 0; i < to_block->number_of_preds(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1743 assert(from_block == to_block->pred_at(i), "all critical edges must be broken");
a61af66fc99e Initial load
duke
parents:
diff changeset
1744 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1745 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1746
a61af66fc99e Initial load
duke
parents:
diff changeset
1747 move_resolver.set_insert_position(to_block->lir(), 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1748 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1749 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1750
a61af66fc99e Initial load
duke
parents:
diff changeset
1751
a61af66fc99e Initial load
duke
parents:
diff changeset
1752 // insert necessary moves (spilling or reloading) at edges between blocks if interval has been split
a61af66fc99e Initial load
duke
parents:
diff changeset
1753 void LinearScan::resolve_data_flow() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1754 TIME_LINEAR_SCAN(timer_resolve_data_flow);
a61af66fc99e Initial load
duke
parents:
diff changeset
1755
a61af66fc99e Initial load
duke
parents:
diff changeset
1756 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1757 MoveResolver move_resolver(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
1758 BitMap block_completed(num_blocks); block_completed.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
1759 BitMap already_resolved(num_blocks); already_resolved.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
1760
a61af66fc99e Initial load
duke
parents:
diff changeset
1761 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1762 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1763 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1764
a61af66fc99e Initial load
duke
parents:
diff changeset
1765 // check if block has only one predecessor and only one successor
a61af66fc99e Initial load
duke
parents:
diff changeset
1766 if (block->number_of_preds() == 1 && block->number_of_sux() == 1 && block->number_of_exception_handlers() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1767 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1768 assert(instructions->at(0)->code() == lir_label, "block must start with label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1769 assert(instructions->last()->code() == lir_branch, "block with successors must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
1770 assert(instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block with successor must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
1771
a61af66fc99e Initial load
duke
parents:
diff changeset
1772 // check if block is empty (only label and branch)
a61af66fc99e Initial load
duke
parents:
diff changeset
1773 if (instructions->length() == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1774 BlockBegin* pred = block->pred_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1775 BlockBegin* sux = block->sux_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1776
a61af66fc99e Initial load
duke
parents:
diff changeset
1777 // prevent optimization of two consecutive blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1778 if (!block_completed.at(pred->linear_scan_number()) && !block_completed.at(sux->linear_scan_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1779 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1780 block_completed.set_bit(block->linear_scan_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
1781
a61af66fc99e Initial load
duke
parents:
diff changeset
1782 // directly resolve between pred and sux (without looking at the empty block between)
a61af66fc99e Initial load
duke
parents:
diff changeset
1783 resolve_collect_mappings(pred, sux, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1784 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1785 move_resolver.set_insert_position(block->lir(), 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1786 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1787 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1788 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1789 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1790 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1791 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1792
a61af66fc99e Initial load
duke
parents:
diff changeset
1793
a61af66fc99e Initial load
duke
parents:
diff changeset
1794 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1795 if (!block_completed.at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1796 BlockBegin* from_block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1797 already_resolved.set_from(block_completed);
a61af66fc99e Initial load
duke
parents:
diff changeset
1798
a61af66fc99e Initial load
duke
parents:
diff changeset
1799 int num_sux = from_block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
1800 for (int s = 0; s < num_sux; s++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1801 BlockBegin* to_block = from_block->sux_at(s);
a61af66fc99e Initial load
duke
parents:
diff changeset
1802
a61af66fc99e Initial load
duke
parents:
diff changeset
1803 // check for duplicate edges between the same blocks (can happen with switch blocks)
a61af66fc99e Initial load
duke
parents:
diff changeset
1804 if (!already_resolved.at(to_block->linear_scan_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1805 TRACE_LINEAR_SCAN(3, tty->print_cr("**** processing edge between B%d and B%d", from_block->block_id(), to_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1806 already_resolved.set_bit(to_block->linear_scan_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
1807
a61af66fc99e Initial load
duke
parents:
diff changeset
1808 // collect all intervals that have been split between from_block and to_block
a61af66fc99e Initial load
duke
parents:
diff changeset
1809 resolve_collect_mappings(from_block, to_block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1810 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1811 resolve_find_insert_pos(from_block, to_block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1812 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1813 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1814 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1816 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1817 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1818 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1819
a61af66fc99e Initial load
duke
parents:
diff changeset
1820
a61af66fc99e Initial load
duke
parents:
diff changeset
1821 void LinearScan::resolve_exception_entry(BlockBegin* block, int reg_num, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1822 if (interval_at(reg_num) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1823 // if a phi function is never used, no interval is created -> ignore this
a61af66fc99e Initial load
duke
parents:
diff changeset
1824 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1825 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1826
a61af66fc99e Initial load
duke
parents:
diff changeset
1827 Interval* interval = interval_at_block_begin(block, reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1828 int reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
1829 int regHi = interval->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
1830
a61af66fc99e Initial load
duke
parents:
diff changeset
1831 if ((reg < nof_regs && interval->always_in_memory()) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
1832 (use_fpu_stack_allocation() && reg >= pd_first_fpu_reg && reg <= pd_last_fpu_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1833 // the interval is split to get a short range that is located on the stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1834 // in the following two cases:
a61af66fc99e Initial load
duke
parents:
diff changeset
1835 // * the interval started in memory (e.g. method parameter), but is currently in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1836 // this is an optimization for exception handling that reduces the number of moves that
a61af66fc99e Initial load
duke
parents:
diff changeset
1837 // are necessary for resolving the states when an exception uses this exception handler
a61af66fc99e Initial load
duke
parents:
diff changeset
1838 // * the interval would be on the fpu stack at the begin of the exception handler
a61af66fc99e Initial load
duke
parents:
diff changeset
1839 // this is not allowed because of the complicated fpu stack handling on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
1840
a61af66fc99e Initial load
duke
parents:
diff changeset
1841 // range that will be spilled to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
1842 int from_op_id = block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1843 int to_op_id = from_op_id + 1; // short live range of length 1
a61af66fc99e Initial load
duke
parents:
diff changeset
1844 assert(interval->from() <= from_op_id && interval->to() >= to_op_id,
a61af66fc99e Initial load
duke
parents:
diff changeset
1845 "no split allowed between exception entry and first instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
1846
a61af66fc99e Initial load
duke
parents:
diff changeset
1847 if (interval->from() != from_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1848 // the part before from_op_id is unchanged
a61af66fc99e Initial load
duke
parents:
diff changeset
1849 interval = interval->split(from_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1850 interval->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
1851 append_interval(interval);
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1852 } else {
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1853 _needs_full_resort = true;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1854 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1855 assert(interval->from() == from_op_id, "must be true now");
a61af66fc99e Initial load
duke
parents:
diff changeset
1856
a61af66fc99e Initial load
duke
parents:
diff changeset
1857 Interval* spilled_part = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1858 if (interval->to() != to_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1859 // the part after to_op_id is unchanged
a61af66fc99e Initial load
duke
parents:
diff changeset
1860 spilled_part = interval->split_from_start(to_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1861 append_interval(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
1862 move_resolver.add_mapping(spilled_part, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1863 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1864 assign_spill_slot(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
1865
a61af66fc99e Initial load
duke
parents:
diff changeset
1866 assert(spilled_part->from() == from_op_id && spilled_part->to() == to_op_id, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
1867 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1868 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1869
a61af66fc99e Initial load
duke
parents:
diff changeset
1870 void LinearScan::resolve_exception_entry(BlockBegin* block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1871 assert(block->is_set(BlockBegin::exception_entry_flag), "should not call otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1872 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1873
a61af66fc99e Initial load
duke
parents:
diff changeset
1874 // visit all registers where the live_in bit is set
a61af66fc99e Initial load
duke
parents:
diff changeset
1875 int size = live_set_size();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1876 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)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1877 resolve_exception_entry(block, r, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1878 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1879
a61af66fc99e Initial load
duke
parents:
diff changeset
1880 // the live_in bits are not set for phi functions of the xhandler entry, so iterate them separately
a61af66fc99e Initial load
duke
parents:
diff changeset
1881 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
1882 resolve_exception_entry(block, phi->operand()->vreg_number(), move_resolver)
a61af66fc99e Initial load
duke
parents:
diff changeset
1883 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1884
a61af66fc99e Initial load
duke
parents:
diff changeset
1885 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1886 // insert moves after first instruction
5906
b279f99d7143 6910461: Register allocator may insert spill code at wrong insertion index
roland
parents: 4948
diff changeset
1887 move_resolver.set_insert_position(block->lir(), 0);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1888 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1889 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1890 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1891
a61af66fc99e Initial load
duke
parents:
diff changeset
1892
a61af66fc99e Initial load
duke
parents:
diff changeset
1893 void LinearScan::resolve_exception_edge(XHandler* handler, int throwing_op_id, int reg_num, Phi* phi, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1894 if (interval_at(reg_num) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1895 // if a phi function is never used, no interval is created -> ignore this
a61af66fc99e Initial load
duke
parents:
diff changeset
1896 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1897 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1898
a61af66fc99e Initial load
duke
parents:
diff changeset
1899 // the computation of to_interval is equal to resolve_collect_mappings,
a61af66fc99e Initial load
duke
parents:
diff changeset
1900 // but from_interval is more complicated because of phi functions
a61af66fc99e Initial load
duke
parents:
diff changeset
1901 BlockBegin* to_block = handler->entry_block();
a61af66fc99e Initial load
duke
parents:
diff changeset
1902 Interval* to_interval = interval_at_block_begin(to_block, reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1903
a61af66fc99e Initial load
duke
parents:
diff changeset
1904 if (phi != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1905 // phi function of the exception entry block
a61af66fc99e Initial load
duke
parents:
diff changeset
1906 // no moves are created for this phi function in the LIR_Generator, so the
a61af66fc99e Initial load
duke
parents:
diff changeset
1907 // interval at the throwing instruction must be searched using the operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1908 // of the phi function
a61af66fc99e Initial load
duke
parents:
diff changeset
1909 Value from_value = phi->operand_at(handler->phi_operand());
a61af66fc99e Initial load
duke
parents:
diff changeset
1910
a61af66fc99e Initial load
duke
parents:
diff changeset
1911 // with phi functions it can happen that the same from_value is used in
a61af66fc99e Initial load
duke
parents:
diff changeset
1912 // multiple mappings, so notify move-resolver that this is allowed
a61af66fc99e Initial load
duke
parents:
diff changeset
1913 move_resolver.set_multiple_reads_allowed();
a61af66fc99e Initial load
duke
parents:
diff changeset
1914
a61af66fc99e Initial load
duke
parents:
diff changeset
1915 Constant* con = from_value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
1916 if (con != NULL && !con->is_pinned()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1917 // unpinned constants may have no register, so add mapping from constant to interval
a61af66fc99e Initial load
duke
parents:
diff changeset
1918 move_resolver.add_mapping(LIR_OprFact::value_type(con->type()), to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1919 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1920 // search split child at the throwing op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
1921 Interval* from_interval = interval_at_op_id(from_value->operand()->vreg_number(), throwing_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1922 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1923 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1924
a61af66fc99e Initial load
duke
parents:
diff changeset
1925 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1926 // no phi function, so use reg_num also for from_interval
a61af66fc99e Initial load
duke
parents:
diff changeset
1927 // search split child at the throwing op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
1928 Interval* from_interval = interval_at_op_id(reg_num, throwing_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1929 if (from_interval != to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1930 // optimization to reduce number of moves: when to_interval is on stack and
a61af66fc99e Initial load
duke
parents:
diff changeset
1931 // the stack slot is known to be always correct, then no move is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
1932 if (!from_interval->always_in_memory() || from_interval->canonical_spill_slot() != to_interval->assigned_reg()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1933 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1934 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1935 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1936 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1937 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1938
a61af66fc99e Initial load
duke
parents:
diff changeset
1939 void LinearScan::resolve_exception_edge(XHandler* handler, int throwing_op_id, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1940 TRACE_LINEAR_SCAN(4, tty->print_cr("resolving exception handler B%d: throwing_op_id=%d", handler->entry_block()->block_id(), throwing_op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
1941
a61af66fc99e Initial load
duke
parents:
diff changeset
1942 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1943 assert(handler->lir_op_id() == -1, "already processed this xhandler");
a61af66fc99e Initial load
duke
parents:
diff changeset
1944 DEBUG_ONLY(handler->set_lir_op_id(throwing_op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
1945 assert(handler->entry_code() == NULL, "code already present");
a61af66fc99e Initial load
duke
parents:
diff changeset
1946
a61af66fc99e Initial load
duke
parents:
diff changeset
1947 // visit all registers where the live_in bit is set
a61af66fc99e Initial load
duke
parents:
diff changeset
1948 BlockBegin* block = handler->entry_block();
a61af66fc99e Initial load
duke
parents:
diff changeset
1949 int size = live_set_size();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1950 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)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1951 resolve_exception_edge(handler, throwing_op_id, r, NULL, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1952 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1953
a61af66fc99e Initial load
duke
parents:
diff changeset
1954 // the live_in bits are not set for phi functions of the xhandler entry, so iterate them separately
a61af66fc99e Initial load
duke
parents:
diff changeset
1955 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
1956 resolve_exception_edge(handler, throwing_op_id, phi->operand()->vreg_number(), phi, move_resolver)
a61af66fc99e Initial load
duke
parents:
diff changeset
1957 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1958
a61af66fc99e Initial load
duke
parents:
diff changeset
1959 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1960 LIR_List* entry_code = new LIR_List(compilation());
a61af66fc99e Initial load
duke
parents:
diff changeset
1961 move_resolver.set_insert_position(entry_code, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1962 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1963
a61af66fc99e Initial load
duke
parents:
diff changeset
1964 entry_code->jump(handler->entry_block());
a61af66fc99e Initial load
duke
parents:
diff changeset
1965 handler->set_entry_code(entry_code);
a61af66fc99e Initial load
duke
parents:
diff changeset
1966 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1967 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1968
a61af66fc99e Initial load
duke
parents:
diff changeset
1969
a61af66fc99e Initial load
duke
parents:
diff changeset
1970 void LinearScan::resolve_exception_handlers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1971 MoveResolver move_resolver(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
1972 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
1973 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1974
a61af66fc99e Initial load
duke
parents:
diff changeset
1975 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1976 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1977 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1978 if (block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1979 resolve_exception_entry(block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1980 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1981 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1982
a61af66fc99e Initial load
duke
parents:
diff changeset
1983 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1984 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1985 LIR_List* ops = block->lir();
a61af66fc99e Initial load
duke
parents:
diff changeset
1986 int num_ops = ops->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1987
a61af66fc99e Initial load
duke
parents:
diff changeset
1988 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
1989 assert(visitor.no_operands(ops->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1990 for (int j = 1; j < num_ops; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1991 LIR_Op* op = ops->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
1992 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1993
a61af66fc99e Initial load
duke
parents:
diff changeset
1994 if (op_id != -1 && has_info(op_id)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1995 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1996 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1997 assert(visitor.info_count() > 0, "should not visit otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1998
a61af66fc99e Initial load
duke
parents:
diff changeset
1999 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
2000 int n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2001 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2002 resolve_exception_edge(xhandlers->handler_at(k), op_id, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
2003 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2004
a61af66fc99e Initial load
duke
parents:
diff changeset
2005 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2006 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2007 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2008 assert(visitor.all_xhandler()->length() == 0, "missed exception handler");
a61af66fc99e Initial load
duke
parents:
diff changeset
2009 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2010 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2011 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2012 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2013 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2014
a61af66fc99e Initial load
duke
parents:
diff changeset
2015
a61af66fc99e Initial load
duke
parents:
diff changeset
2016 // ********** Phase 7: assign register numbers back to LIR
a61af66fc99e Initial load
duke
parents:
diff changeset
2017 // (includes computation of debug information and oop maps)
a61af66fc99e Initial load
duke
parents:
diff changeset
2018
a61af66fc99e Initial load
duke
parents:
diff changeset
2019 VMReg LinearScan::vm_reg_for_interval(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2020 VMReg reg = interval->cached_vm_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2021 if (!reg->is_valid() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2022 reg = vm_reg_for_operand(operand_for_interval(interval));
a61af66fc99e Initial load
duke
parents:
diff changeset
2023 interval->set_cached_vm_reg(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2024 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2025 assert(reg == vm_reg_for_operand(operand_for_interval(interval)), "wrong cached value");
a61af66fc99e Initial load
duke
parents:
diff changeset
2026 return reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
2027 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2028
a61af66fc99e Initial load
duke
parents:
diff changeset
2029 VMReg LinearScan::vm_reg_for_operand(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2030 assert(opr->is_oop(), "currently only implemented for oop operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2031 return frame_map()->regname(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2032 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2033
a61af66fc99e Initial load
duke
parents:
diff changeset
2034
a61af66fc99e Initial load
duke
parents:
diff changeset
2035 LIR_Opr LinearScan::operand_for_interval(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2036 LIR_Opr opr = interval->cached_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2037 if (opr->is_illegal()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2038 opr = calc_operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
2039 interval->set_cached_opr(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2040 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2041
a61af66fc99e Initial load
duke
parents:
diff changeset
2042 assert(opr == calc_operand_for_interval(interval), "wrong cached value");
a61af66fc99e Initial load
duke
parents:
diff changeset
2043 return opr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2044 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2045
a61af66fc99e Initial load
duke
parents:
diff changeset
2046 LIR_Opr LinearScan::calc_operand_for_interval(const Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2047 int assigned_reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2048 BasicType type = interval->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
2049
a61af66fc99e Initial load
duke
parents:
diff changeset
2050 if (assigned_reg >= nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2051 // stack slot
a61af66fc99e Initial load
duke
parents:
diff changeset
2052 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2053 return LIR_OprFact::stack(assigned_reg - nof_regs, type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2054
a61af66fc99e Initial load
duke
parents:
diff changeset
2055 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2056 // register
a61af66fc99e Initial load
duke
parents:
diff changeset
2057 switch (type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2058 case T_OBJECT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2059 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2060 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2061 return LIR_OprFact::single_cpu_oop(assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2062 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2063
1816
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2064 case T_ADDRESS: {
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2065 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2066 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2067 return LIR_OprFact::single_cpu_address(assigned_reg);
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2068 }
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2069
6739
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2070 case T_METADATA: {
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2071 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2072 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2073 return LIR_OprFact::single_cpu_metadata(assigned_reg);
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2074 }
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2075
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2076 #ifdef __SOFTFP__
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2077 case T_FLOAT: // fall through
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2078 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2079 case T_INT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2080 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2081 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2082 return LIR_OprFact::single_cpu(assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2083 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2084
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2085 #ifdef __SOFTFP__
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2086 case T_DOUBLE: // fall through
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2087 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2088 case T_LONG: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2089 int assigned_regHi = interval->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
2090 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2091 assert(num_physical_regs(T_LONG) == 1 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2092 (assigned_regHi >= pd_first_cpu_reg && assigned_regHi <= pd_last_cpu_reg), "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2093
a61af66fc99e Initial load
duke
parents:
diff changeset
2094 assert(assigned_reg != assigned_regHi, "invalid allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
2095 assert(num_physical_regs(T_LONG) == 1 || assigned_reg < assigned_regHi,
a61af66fc99e Initial load
duke
parents:
diff changeset
2096 "register numbers must be sorted (ensure that e.g. a move from eax,ebx to ebx,eax can not occur)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2097 assert((assigned_regHi != any_reg) ^ (num_physical_regs(T_LONG) == 1), "must be match");
a61af66fc99e Initial load
duke
parents:
diff changeset
2098 if (requires_adjacent_regs(T_LONG)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2099 assert(assigned_reg % 2 == 0 && assigned_reg + 1 == assigned_regHi, "must be sequential and even");
a61af66fc99e Initial load
duke
parents:
diff changeset
2100 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2101
a61af66fc99e Initial load
duke
parents:
diff changeset
2102 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
2103 return LIR_OprFact::double_cpu(assigned_reg, assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2104 #else
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2105 #if defined(SPARC) || defined(PPC)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2106 return LIR_OprFact::double_cpu(assigned_regHi, assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2107 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2108 return LIR_OprFact::double_cpu(assigned_reg, assigned_regHi);
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2109 #endif // SPARC
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2110 #endif // LP64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2111 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2112
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2113 #ifndef __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2114 case T_FLOAT: {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2115 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2116 if (UseSSE >= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2117 assert(assigned_reg >= pd_first_xmm_reg && assigned_reg <= pd_last_xmm_reg, "no xmm register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2118 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2119 return LIR_OprFact::single_xmm(assigned_reg - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2120 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2121 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2122
a61af66fc99e Initial load
duke
parents:
diff changeset
2123 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2124 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2125 return LIR_OprFact::single_fpu(assigned_reg - pd_first_fpu_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2126 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2127
a61af66fc99e Initial load
duke
parents:
diff changeset
2128 case T_DOUBLE: {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2129 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2130 if (UseSSE >= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2131 assert(assigned_reg >= pd_first_xmm_reg && assigned_reg <= pd_last_xmm_reg, "no xmm register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2132 assert(interval->assigned_regHi() == any_reg, "must not have hi register (double xmm values are stored in one register)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2133 return LIR_OprFact::double_xmm(assigned_reg - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2134 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2135 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2136
a61af66fc99e Initial load
duke
parents:
diff changeset
2137 #ifdef SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
2138 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2139 assert(interval->assigned_regHi() >= pd_first_fpu_reg && interval->assigned_regHi() <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2140 assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even");
a61af66fc99e Initial load
duke
parents:
diff changeset
2141 LIR_Opr result = LIR_OprFact::double_fpu(interval->assigned_regHi() - pd_first_fpu_reg, assigned_reg - pd_first_fpu_reg);
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2142 #elif defined(ARM)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2143 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2144 assert(interval->assigned_regHi() >= pd_first_fpu_reg && interval->assigned_regHi() <= pd_last_fpu_reg, "no fpu register");
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2145 assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even");
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2146 LIR_Opr result = LIR_OprFact::double_fpu(assigned_reg - pd_first_fpu_reg, interval->assigned_regHi() - pd_first_fpu_reg);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2147 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2148 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2149 assert(interval->assigned_regHi() == any_reg, "must not have hi register (double fpu values are stored in one register on Intel)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2150 LIR_Opr result = LIR_OprFact::double_fpu(assigned_reg - pd_first_fpu_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2151 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2152 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
2153 }
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2154 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2155
a61af66fc99e Initial load
duke
parents:
diff changeset
2156 default: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2157 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2158 return LIR_OprFact::illegalOpr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2159 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2160 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2162 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2163
a61af66fc99e Initial load
duke
parents:
diff changeset
2164 LIR_Opr LinearScan::canonical_spill_opr(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2165 assert(interval->canonical_spill_slot() >= nof_regs, "canonical spill slot not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
2166 return LIR_OprFact::stack(interval->canonical_spill_slot() - nof_regs, interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
2167 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2168
a61af66fc99e Initial load
duke
parents:
diff changeset
2169 LIR_Opr LinearScan::color_lir_opr(LIR_Opr opr, int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2170 assert(opr->is_virtual(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2171
a61af66fc99e Initial load
duke
parents:
diff changeset
2172 Interval* interval = interval_at(opr->vreg_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
2173 assert(interval != NULL, "interval must exist");
a61af66fc99e Initial load
duke
parents:
diff changeset
2174
a61af66fc99e Initial load
duke
parents:
diff changeset
2175 if (op_id != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2176 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2177 BlockBegin* block = block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2178 if (block->number_of_sux() <= 1 && op_id == block->last_lir_instruction_id()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2179 // check if spill moves could have been appended at the end of this block, but
a61af66fc99e Initial load
duke
parents:
diff changeset
2180 // before the branch instruction. So the split child information for this branch would
a61af66fc99e Initial load
duke
parents:
diff changeset
2181 // be incorrect.
a61af66fc99e Initial load
duke
parents:
diff changeset
2182 LIR_OpBranch* branch = block->lir()->instructions_list()->last()->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
2183 if (branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2184 if (block->live_out().at(opr->vreg_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2185 assert(branch->cond() == lir_cond_always, "block does not end with an unconditional jump");
a61af66fc99e Initial load
duke
parents:
diff changeset
2186 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)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2187 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2190 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2191
a61af66fc99e Initial load
duke
parents:
diff changeset
2192 // operands are not changed when an interval is split during allocation,
a61af66fc99e Initial load
duke
parents:
diff changeset
2193 // so search the right interval here
a61af66fc99e Initial load
duke
parents:
diff changeset
2194 interval = split_child_at_op_id(interval, op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2195 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2196
a61af66fc99e Initial load
duke
parents:
diff changeset
2197 LIR_Opr res = operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
2198
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2199 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2200 // new semantic for is_last_use: not only set on definite end of interval,
a61af66fc99e Initial load
duke
parents:
diff changeset
2201 // but also before hole
a61af66fc99e Initial load
duke
parents:
diff changeset
2202 // This may still miss some cases (e.g. for dead values), but it is not necessary that the
a61af66fc99e Initial load
duke
parents:
diff changeset
2203 // last use information is completely correct
a61af66fc99e Initial load
duke
parents:
diff changeset
2204 // information is only needed for fpu stack allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
2205 if (res->is_fpu_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2206 if (opr->is_last_use() || op_id == interval->to() || (op_id != -1 && interval->has_hole_between(op_id, op_id + 1))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2207 assert(op_id == -1 || !is_block_begin(op_id), "holes at begin of block may also result from control flow");
a61af66fc99e Initial load
duke
parents:
diff changeset
2208 res = res->make_last_use();
a61af66fc99e Initial load
duke
parents:
diff changeset
2209 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2210 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2211 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2212
a61af66fc99e Initial load
duke
parents:
diff changeset
2213 assert(!gen()->is_vreg_flag_set(opr->vreg_number(), LIRGenerator::callee_saved) || !FrameMap::is_caller_save_register(res), "bad allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
2214
a61af66fc99e Initial load
duke
parents:
diff changeset
2215 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
2216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2217
a61af66fc99e Initial load
duke
parents:
diff changeset
2218
a61af66fc99e Initial load
duke
parents:
diff changeset
2219 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2220 // some methods used to check correctness of debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
2221
a61af66fc99e Initial load
duke
parents:
diff changeset
2222 void assert_no_register_values(GrowableArray<ScopeValue*>* values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2223 if (values == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2224 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
2225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2226
a61af66fc99e Initial load
duke
parents:
diff changeset
2227 for (int i = 0; i < values->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2228 ScopeValue* value = values->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2229
a61af66fc99e Initial load
duke
parents:
diff changeset
2230 if (value->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2231 Location location = ((LocationValue*)value)->location();
a61af66fc99e Initial load
duke
parents:
diff changeset
2232 assert(location.where() == Location::on_stack, "value is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2233 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2234 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2235 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2236
a61af66fc99e Initial load
duke
parents:
diff changeset
2237 void assert_no_register_values(GrowableArray<MonitorValue*>* values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2238 if (values == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2239 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
2240 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2241
a61af66fc99e Initial load
duke
parents:
diff changeset
2242 for (int i = 0; i < values->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2243 MonitorValue* value = values->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2244
a61af66fc99e Initial load
duke
parents:
diff changeset
2245 if (value->owner()->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2246 Location location = ((LocationValue*)value->owner())->location();
a61af66fc99e Initial load
duke
parents:
diff changeset
2247 assert(location.where() == Location::on_stack, "owner is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2248 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2249 assert(value->basic_lock().where() == Location::on_stack, "basic_lock is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2252
a61af66fc99e Initial load
duke
parents:
diff changeset
2253 void assert_equal(Location l1, Location l2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2254 assert(l1.where() == l2.where() && l1.type() == l2.type() && l1.offset() == l2.offset(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2255 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2256
a61af66fc99e Initial load
duke
parents:
diff changeset
2257 void assert_equal(ScopeValue* v1, ScopeValue* v2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2258 if (v1->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2259 assert(v2->is_location(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2260 assert_equal(((LocationValue*)v1)->location(), ((LocationValue*)v2)->location());
a61af66fc99e Initial load
duke
parents:
diff changeset
2261 } else if (v1->is_constant_int()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2262 assert(v2->is_constant_int(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2263 assert(((ConstantIntValue*)v1)->value() == ((ConstantIntValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2264 } else if (v1->is_constant_double()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2265 assert(v2->is_constant_double(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2266 assert(((ConstantDoubleValue*)v1)->value() == ((ConstantDoubleValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2267 } else if (v1->is_constant_long()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2268 assert(v2->is_constant_long(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2269 assert(((ConstantLongValue*)v1)->value() == ((ConstantLongValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2270 } else if (v1->is_constant_oop()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2271 assert(v2->is_constant_oop(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2272 assert(((ConstantOopWriteValue*)v1)->value() == ((ConstantOopWriteValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2273 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2274 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2275 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2276 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2277
a61af66fc99e Initial load
duke
parents:
diff changeset
2278 void assert_equal(MonitorValue* m1, MonitorValue* m2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2279 assert_equal(m1->owner(), m2->owner());
a61af66fc99e Initial load
duke
parents:
diff changeset
2280 assert_equal(m1->basic_lock(), m2->basic_lock());
a61af66fc99e Initial load
duke
parents:
diff changeset
2281 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2282
a61af66fc99e Initial load
duke
parents:
diff changeset
2283 void assert_equal(IRScopeDebugInfo* d1, IRScopeDebugInfo* d2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2284 assert(d1->scope() == d2->scope(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2285 assert(d1->bci() == d2->bci(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2286
a61af66fc99e Initial load
duke
parents:
diff changeset
2287 if (d1->locals() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2288 assert(d1->locals() != NULL && d2->locals() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2289 assert(d1->locals()->length() == d2->locals()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2290 for (int i = 0; i < d1->locals()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2291 assert_equal(d1->locals()->at(i), d2->locals()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2292 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2293 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2294 assert(d1->locals() == NULL && d2->locals() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2295 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2296
a61af66fc99e Initial load
duke
parents:
diff changeset
2297 if (d1->expressions() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2298 assert(d1->expressions() != NULL && d2->expressions() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2299 assert(d1->expressions()->length() == d2->expressions()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2300 for (int i = 0; i < d1->expressions()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2301 assert_equal(d1->expressions()->at(i), d2->expressions()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2302 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2303 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2304 assert(d1->expressions() == NULL && d2->expressions() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2305 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2306
a61af66fc99e Initial load
duke
parents:
diff changeset
2307 if (d1->monitors() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2308 assert(d1->monitors() != NULL && d2->monitors() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2309 assert(d1->monitors()->length() == d2->monitors()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2310 for (int i = 0; i < d1->monitors()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2311 assert_equal(d1->monitors()->at(i), d2->monitors()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2312 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2313 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2314 assert(d1->monitors() == NULL && d2->monitors() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2315 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2316
a61af66fc99e Initial load
duke
parents:
diff changeset
2317 if (d1->caller() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2318 assert(d1->caller() != NULL && d2->caller() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2319 assert_equal(d1->caller(), d2->caller());
a61af66fc99e Initial load
duke
parents:
diff changeset
2320 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2321 assert(d1->caller() == NULL && d2->caller() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2322 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2323 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2324
a61af66fc99e Initial load
duke
parents:
diff changeset
2325 void check_stack_depth(CodeEmitInfo* info, int stack_end) {
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2326 if (info->stack()->bci() != SynchronizationEntryBCI && !info->scope()->method()->is_native()) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2327 Bytecodes::Code code = info->scope()->method()->java_code_at_bci(info->stack()->bci());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2328 switch (code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2329 case Bytecodes::_ifnull : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2330 case Bytecodes::_ifnonnull : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2331 case Bytecodes::_ifeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2332 case Bytecodes::_ifne : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2333 case Bytecodes::_iflt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2334 case Bytecodes::_ifge : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2335 case Bytecodes::_ifgt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2336 case Bytecodes::_ifle : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2337 case Bytecodes::_if_icmpeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2338 case Bytecodes::_if_icmpne : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2339 case Bytecodes::_if_icmplt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2340 case Bytecodes::_if_icmpge : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2341 case Bytecodes::_if_icmpgt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2342 case Bytecodes::_if_icmple : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2343 case Bytecodes::_if_acmpeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2344 case Bytecodes::_if_acmpne :
a61af66fc99e Initial load
duke
parents:
diff changeset
2345 assert(stack_end >= -Bytecodes::depth(code), "must have non-empty expression stack at if bytecode");
a61af66fc99e Initial load
duke
parents:
diff changeset
2346 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2347 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2348 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2349 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2350
a61af66fc99e Initial load
duke
parents:
diff changeset
2351 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2352
a61af66fc99e Initial load
duke
parents:
diff changeset
2353
a61af66fc99e Initial load
duke
parents:
diff changeset
2354 IntervalWalker* LinearScan::init_compute_oop_maps() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2355 // setup lists of potential oops for walking
a61af66fc99e Initial load
duke
parents:
diff changeset
2356 Interval* oop_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
2357 Interval* non_oop_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
2358
a61af66fc99e Initial load
duke
parents:
diff changeset
2359 create_unhandled_lists(&oop_intervals, &non_oop_intervals, is_oop_interval, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2360
a61af66fc99e Initial load
duke
parents:
diff changeset
2361 // intervals that have no oops inside need not to be processed
a61af66fc99e Initial load
duke
parents:
diff changeset
2362 // to ensure a walking until the last instruction id, add a dummy interval
a61af66fc99e Initial load
duke
parents:
diff changeset
2363 // with a high operation id
a61af66fc99e Initial load
duke
parents:
diff changeset
2364 non_oop_intervals = new Interval(any_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2365 non_oop_intervals->add_range(max_jint - 2, max_jint - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2366
a61af66fc99e Initial load
duke
parents:
diff changeset
2367 return new IntervalWalker(this, oop_intervals, non_oop_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2368 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2369
a61af66fc99e Initial load
duke
parents:
diff changeset
2370
a61af66fc99e Initial load
duke
parents:
diff changeset
2371 OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo* info, bool is_call_site) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2372 TRACE_LINEAR_SCAN(3, tty->print_cr("creating oop map at op_id %d", op->id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2373
a61af66fc99e Initial load
duke
parents:
diff changeset
2374 // walk before the current operation -> intervals that start at
a61af66fc99e Initial load
duke
parents:
diff changeset
2375 // the operation (= output operands of the operation) are not
a61af66fc99e Initial load
duke
parents:
diff changeset
2376 // included in the oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2377 iw->walk_before(op->id());
a61af66fc99e Initial load
duke
parents:
diff changeset
2378
a61af66fc99e Initial load
duke
parents:
diff changeset
2379 int frame_size = frame_map()->framesize();
a61af66fc99e Initial load
duke
parents:
diff changeset
2380 int arg_count = frame_map()->oop_map_arg_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
2381 OopMap* map = new OopMap(frame_size, arg_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2382
a61af66fc99e Initial load
duke
parents:
diff changeset
2383 // Check if this is a patch site.
a61af66fc99e Initial load
duke
parents:
diff changeset
2384 bool is_patch_info = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
2385 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2386 assert(!is_call_site, "move must not be a call site");
a61af66fc99e Initial load
duke
parents:
diff changeset
2387 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
2388 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
2389
a61af66fc99e Initial load
duke
parents:
diff changeset
2390 is_patch_info = move->patch_code() != lir_patch_none;
a61af66fc99e Initial load
duke
parents:
diff changeset
2391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2392
a61af66fc99e Initial load
duke
parents:
diff changeset
2393 // Iterate through active intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
2394 for (Interval* interval = iw->active_first(fixedKind); interval != Interval::end(); interval = interval->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2395 int assigned_reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2396
a61af66fc99e Initial load
duke
parents:
diff changeset
2397 assert(interval->current_from() <= op->id() && op->id() <= interval->current_to(), "interval should not be active otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2398 assert(interval->assigned_regHi() == any_reg, "oop must be single word");
a61af66fc99e Initial load
duke
parents:
diff changeset
2399 assert(interval->reg_num() >= LIR_OprDesc::vreg_base, "fixed interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
2400
a61af66fc99e Initial load
duke
parents:
diff changeset
2401 // Check if this range covers the instruction. Intervals that
a61af66fc99e Initial load
duke
parents:
diff changeset
2402 // start or end at the current operation are not included in the
a61af66fc99e Initial load
duke
parents:
diff changeset
2403 // oop map, except in the case of patching moves. For patching
a61af66fc99e Initial load
duke
parents:
diff changeset
2404 // moves, any intervals which end at this instruction are included
a61af66fc99e Initial load
duke
parents:
diff changeset
2405 // in the oop map since we may safepoint while doing the patch
a61af66fc99e Initial load
duke
parents:
diff changeset
2406 // before we've consumed the inputs.
a61af66fc99e Initial load
duke
parents:
diff changeset
2407 if (is_patch_info || op->id() < interval->current_to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2408
a61af66fc99e Initial load
duke
parents:
diff changeset
2409 // caller-save registers must not be included into oop-maps at calls
a61af66fc99e Initial load
duke
parents:
diff changeset
2410 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");
a61af66fc99e Initial load
duke
parents:
diff changeset
2411
a61af66fc99e Initial load
duke
parents:
diff changeset
2412 VMReg name = vm_reg_for_interval(interval);
3908
7588156f5cf9 7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents: 2426
diff changeset
2413 set_oop(map, name);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2414
a61af66fc99e Initial load
duke
parents:
diff changeset
2415 // Spill optimization: when the stack value is guaranteed to be always correct,
a61af66fc99e Initial load
duke
parents:
diff changeset
2416 // then it must be added to the oop map even if the interval is currently in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
2417 if (interval->always_in_memory() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2418 op->id() > interval->spill_definition_pos() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2419 interval->assigned_reg() != interval->canonical_spill_slot()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2420 assert(interval->spill_definition_pos() > 0, "position not set correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
2421 assert(interval->canonical_spill_slot() >= LinearScan::nof_regs, "no spill slot assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
2422 assert(interval->assigned_reg() < LinearScan::nof_regs, "interval is on stack, so stack slot is registered twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
2423
3908
7588156f5cf9 7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents: 2426
diff changeset
2424 set_oop(map, frame_map()->slot_regname(interval->canonical_spill_slot() - LinearScan::nof_regs));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2425 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2426 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2427 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2428
a61af66fc99e Initial load
duke
parents:
diff changeset
2429 // add oops from lock stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2430 assert(info->stack() != NULL, "CodeEmitInfo must always have a stack");
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2431 int locks_count = info->stack()->total_locks_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2432 for (int i = 0; i < locks_count; i++) {
3908
7588156f5cf9 7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents: 2426
diff changeset
2433 set_oop(map, frame_map()->monitor_object_regname(i));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2434 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2435
a61af66fc99e Initial load
duke
parents:
diff changeset
2436 return map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2437 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2438
a61af66fc99e Initial load
duke
parents:
diff changeset
2439
a61af66fc99e Initial load
duke
parents:
diff changeset
2440 void LinearScan::compute_oop_map(IntervalWalker* iw, const LIR_OpVisitState &visitor, LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2441 assert(visitor.info_count() > 0, "no oop map needed");
a61af66fc99e Initial load
duke
parents:
diff changeset
2442
a61af66fc99e Initial load
duke
parents:
diff changeset
2443 // compute oop_map only for first CodeEmitInfo
a61af66fc99e Initial load
duke
parents:
diff changeset
2444 // because it is (in most cases) equal for all other infos of the same operation
a61af66fc99e Initial load
duke
parents:
diff changeset
2445 CodeEmitInfo* first_info = visitor.info_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2446 OopMap* first_oop_map = compute_oop_map(iw, op, first_info, visitor.has_call());
a61af66fc99e Initial load
duke
parents:
diff changeset
2447
a61af66fc99e Initial load
duke
parents:
diff changeset
2448 for (int i = 0; i < visitor.info_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2449 CodeEmitInfo* info = visitor.info_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2450 OopMap* oop_map = first_oop_map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2451
a61af66fc99e Initial load
duke
parents:
diff changeset
2452 if (info->stack()->locks_size() != first_info->stack()->locks_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2453 // this info has a different number of locks then the precomputed oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2454 // (possible for lock and unlock instructions) -> compute oop map with
a61af66fc99e Initial load
duke
parents:
diff changeset
2455 // correct lock information
a61af66fc99e Initial load
duke
parents:
diff changeset
2456 oop_map = compute_oop_map(iw, op, info, visitor.has_call());
a61af66fc99e Initial load
duke
parents:
diff changeset
2457 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2458
a61af66fc99e Initial load
duke
parents:
diff changeset
2459 if (info->_oop_map == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2460 info->_oop_map = oop_map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2461 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2462 // a CodeEmitInfo can not be shared between different LIR-instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
2463 // because interval splitting can occur anywhere between two instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
2464 // and so the oop maps must be different
a61af66fc99e Initial load
duke
parents:
diff changeset
2465 // -> check if the already set oop_map is exactly the one calculated for this operation
a61af66fc99e Initial load
duke
parents:
diff changeset
2466 assert(info->_oop_map == oop_map, "same CodeEmitInfo used for multiple LIR instructions");
a61af66fc99e Initial load
duke
parents:
diff changeset
2467 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2468 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2469 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2470
a61af66fc99e Initial load
duke
parents:
diff changeset
2471
a61af66fc99e Initial load
duke
parents:
diff changeset
2472 // frequently used constants
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2473 // Allocate them with new so they are never destroyed (otherwise, a
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2474 // forced exit could destroy these objects while they are still in
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2475 // use).
6197
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2476 ConstantOopWriteValue* LinearScan::_oop_null_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantOopWriteValue(NULL);
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2477 ConstantIntValue* LinearScan::_int_m1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(-1);
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2478 ConstantIntValue* LinearScan::_int_0_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(0);
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2479 ConstantIntValue* LinearScan::_int_1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(1);
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2480 ConstantIntValue* LinearScan::_int_2_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(2);
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2481 LocationValue* _illegal_value = new (ResourceObj::C_HEAP, mtCompiler) LocationValue(Location());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2482
a61af66fc99e Initial load
duke
parents:
diff changeset
2483 void LinearScan::init_compute_debug_info() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2484 // cache for frequently used scope values
a61af66fc99e Initial load
duke
parents:
diff changeset
2485 // (cpu registers and stack slots)
a61af66fc99e Initial load
duke
parents:
diff changeset
2486 _scope_value_cache = ScopeValueArray((LinearScan::nof_cpu_regs + frame_map()->argcount() + max_spills()) * 2, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2488
a61af66fc99e Initial load
duke
parents:
diff changeset
2489 MonitorValue* LinearScan::location_for_monitor_index(int monitor_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2490 Location loc;
a61af66fc99e Initial load
duke
parents:
diff changeset
2491 if (!frame_map()->location_for_monitor_object(monitor_index, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2492 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2493 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2494 ScopeValue* object_scope_value = new LocationValue(loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2495
a61af66fc99e Initial load
duke
parents:
diff changeset
2496 if (!frame_map()->location_for_monitor_lock(monitor_index, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2497 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2499 return new MonitorValue(object_scope_value, loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2500 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2501
a61af66fc99e Initial load
duke
parents:
diff changeset
2502 LocationValue* LinearScan::location_for_name(int name, Location::Type loc_type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2503 Location loc;
a61af66fc99e Initial load
duke
parents:
diff changeset
2504 if (!frame_map()->locations_for_slot(name, loc_type, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2505 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2506 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2507 return new LocationValue(loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2508 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2509
a61af66fc99e Initial load
duke
parents:
diff changeset
2510
a61af66fc99e Initial load
duke
parents:
diff changeset
2511 int LinearScan::append_scope_value_for_constant(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2512 assert(opr->is_constant(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2513
a61af66fc99e Initial load
duke
parents:
diff changeset
2514 LIR_Const* c = opr->as_constant_ptr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2515 BasicType t = c->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
2516 switch (t) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2517 case T_OBJECT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2518 jobject value = c->as_jobject();
a61af66fc99e Initial load
duke
parents:
diff changeset
2519 if (value == NULL) {
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2520 scope_values->append(_oop_null_scope_value);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2521 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2522 scope_values->append(new ConstantOopWriteValue(c->as_jobject()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2523 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2524 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2525 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2526
a61af66fc99e Initial load
duke
parents:
diff changeset
2527 case T_INT: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2528 case T_FLOAT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2529 int value = c->as_jint_bits();
a61af66fc99e Initial load
duke
parents:
diff changeset
2530 switch (value) {
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2531 case -1: scope_values->append(_int_m1_scope_value); break;
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2532 case 0: scope_values->append(_int_0_scope_value); break;
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2533 case 1: scope_values->append(_int_1_scope_value); break;
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2534 case 2: scope_values->append(_int_2_scope_value); break;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2535 default: scope_values->append(new ConstantIntValue(c->as_jint_bits())); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2536 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2537 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2538 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2539
a61af66fc99e Initial load
duke
parents:
diff changeset
2540 case T_LONG: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2541 case T_DOUBLE: {
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2542 #ifdef _LP64
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2543 scope_values->append(_int_0_scope_value);
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2544 scope_values->append(new ConstantLongValue(c->as_jlong_bits()));
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2545 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2546 if (hi_word_offset_in_bytes > lo_word_offset_in_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2547 scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2548 scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2549 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2550 scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2551 scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2552 }
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2553 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2554 return 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2555 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2556
1297
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2557 case T_ADDRESS: {
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2558 #ifdef _LP64
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2559 scope_values->append(new ConstantLongValue(c->as_jint()));
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2560 #else
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2561 scope_values->append(new ConstantIntValue(c->as_jint()));
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2562 #endif
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2563 return 1;
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2564 }
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2565
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2566 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
2567 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2568 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2569 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2571
a61af66fc99e Initial load
duke
parents:
diff changeset
2572 int LinearScan::append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2573 if (opr->is_single_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2574 int stack_idx = opr->single_stack_ix();
a61af66fc99e Initial load
duke
parents:
diff changeset
2575 bool is_oop = opr->is_oop_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
2576 int cache_idx = (stack_idx + LinearScan::nof_cpu_regs) * 2 + (is_oop ? 1 : 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2577
a61af66fc99e Initial load
duke
parents:
diff changeset
2578 ScopeValue* sv = _scope_value_cache.at(cache_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
2579 if (sv == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2580 Location::Type loc_type = is_oop ? Location::oop : Location::normal;
a61af66fc99e Initial load
duke
parents:
diff changeset
2581 sv = location_for_name(stack_idx, loc_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2582 _scope_value_cache.at_put(cache_idx, sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2583 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2584
a61af66fc99e Initial load
duke
parents:
diff changeset
2585 // check if cached value is correct
a61af66fc99e Initial load
duke
parents:
diff changeset
2586 DEBUG_ONLY(assert_equal(sv, location_for_name(stack_idx, is_oop ? Location::oop : Location::normal)));
a61af66fc99e Initial load
duke
parents:
diff changeset
2587
a61af66fc99e Initial load
duke
parents:
diff changeset
2588 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2589 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2590
a61af66fc99e Initial load
duke
parents:
diff changeset
2591 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2592 bool is_oop = opr->is_oop_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
2593 int cache_idx = opr->cpu_regnr() * 2 + (is_oop ? 1 : 0);
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2594 Location::Type int_loc_type = NOT_LP64(Location::normal) LP64_ONLY(Location::int_in_long);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2595
a61af66fc99e Initial load
duke
parents:
diff changeset
2596 ScopeValue* sv = _scope_value_cache.at(cache_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
2597 if (sv == NULL) {
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2598 Location::Type loc_type = is_oop ? Location::oop : int_loc_type;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2599 VMReg rname = frame_map()->regname(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2600 sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2601 _scope_value_cache.at_put(cache_idx, sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2602 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2603
a61af66fc99e Initial load
duke
parents:
diff changeset
2604 // check if cached value is correct
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2605 DEBUG_ONLY(assert_equal(sv, new LocationValue(Location::new_reg_loc(is_oop ? Location::oop : int_loc_type, frame_map()->regname(opr)))));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2606
a61af66fc99e Initial load
duke
parents:
diff changeset
2607 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2608 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2609
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2610 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2611 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2612 VMReg rname = opr->as_xmm_float_reg()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2613 LocationValue* sv = new LocationValue(Location::new_reg_loc(Location::normal, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2614
a61af66fc99e Initial load
duke
parents:
diff changeset
2615 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2616 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2617 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2618
a61af66fc99e Initial load
duke
parents:
diff changeset
2619 } else if (opr->is_single_fpu()) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2620 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2621 // the exact location of fpu stack values is only known
a61af66fc99e Initial load
duke
parents:
diff changeset
2622 // during fpu stack allocation, so the stack allocator object
a61af66fc99e Initial load
duke
parents:
diff changeset
2623 // must be present
a61af66fc99e Initial load
duke
parents:
diff changeset
2624 assert(use_fpu_stack_allocation(), "should not have float stack values without fpu stack allocation (all floats must be SSE2)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2625 assert(_fpu_stack_allocator != NULL, "must be present");
a61af66fc99e Initial load
duke
parents:
diff changeset
2626 opr = _fpu_stack_allocator->to_fpu_stack(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2627 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2628
a61af66fc99e Initial load
duke
parents:
diff changeset
2629 Location::Type loc_type = float_saved_as_double ? Location::float_in_dbl : Location::normal;
a61af66fc99e Initial load
duke
parents:
diff changeset
2630 VMReg rname = frame_map()->fpu_regname(opr->fpu_regnr());
3999
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2631 #ifndef __SOFTFP__
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2632 #ifndef VM_LITTLE_ENDIAN
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2633 if (! float_saved_as_double) {
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2634 // On big endian system, we may have an issue if float registers use only
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2635 // the low half of the (same) double registers.
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2636 // Both the float and the double could have the same regnr but would correspond
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2637 // to two different addresses once saved.
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2638
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2639 // get next safely (no assertion checks)
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2640 VMReg next = VMRegImpl::as_VMReg(1+rname->value());
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2641 if (next->is_reg() &&
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2642 (next->as_FloatRegister() == rname->as_FloatRegister())) {
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2643 // the back-end does use the same numbering for the double and the float
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2644 rname = next; // VMReg for the low bits, e.g. the real VMReg for the float
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2645 }
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2646 }
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2647 #endif
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2648 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2649 LocationValue* sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2650
a61af66fc99e Initial load
duke
parents:
diff changeset
2651 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2652 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2653
a61af66fc99e Initial load
duke
parents:
diff changeset
2654 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2655 // double-size operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2656
a61af66fc99e Initial load
duke
parents:
diff changeset
2657 ScopeValue* first;
a61af66fc99e Initial load
duke
parents:
diff changeset
2658 ScopeValue* second;
a61af66fc99e Initial load
duke
parents:
diff changeset
2659
a61af66fc99e Initial load
duke
parents:
diff changeset
2660 if (opr->is_double_stack()) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2661 #ifdef _LP64
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2662 Location loc1;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2663 Location::Type loc_type = opr->type() == T_LONG ? Location::lng : Location::dbl;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2664 if (!frame_map()->locations_for_slot(opr->double_stack_ix(), loc_type, &loc1, NULL)) {
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2665 bailout("too large frame");
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2666 }
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2667 // Does this reverse on x86 vs. sparc?
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2668 first = new LocationValue(loc1);
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2669 second = _int_0_scope_value;
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2670 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2671 Location loc1, loc2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2672 if (!frame_map()->locations_for_slot(opr->double_stack_ix(), Location::normal, &loc1, &loc2)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2673 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2674 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2675 first = new LocationValue(loc1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2676 second = new LocationValue(loc2);
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2677 #endif // _LP64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2678
a61af66fc99e Initial load
duke
parents:
diff changeset
2679 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2680 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
2681 VMReg rname_first = opr->as_register_lo()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2682 first = new LocationValue(Location::new_reg_loc(Location::lng, rname_first));
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2683 second = _int_0_scope_value;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2684 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2685 VMReg rname_first = opr->as_register_lo()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2686 VMReg rname_second = opr->as_register_hi()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2687
a61af66fc99e Initial load
duke
parents:
diff changeset
2688 if (hi_word_offset_in_bytes < lo_word_offset_in_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2689 // lo/hi and swapped relative to first and second, so swap them
a61af66fc99e Initial load
duke
parents:
diff changeset
2690 VMReg tmp = rname_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
2691 rname_first = rname_second;
a61af66fc99e Initial load
duke
parents:
diff changeset
2692 rname_second = tmp;
a61af66fc99e Initial load
duke
parents:
diff changeset
2693 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2694
a61af66fc99e Initial load
duke
parents:
diff changeset
2695 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2696 second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2697 #endif //_LP64
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2698
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2699
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2700 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2701 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2702 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
2703 VMReg rname_first = opr->as_xmm_double_reg()->as_VMReg();
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2704 # ifdef _LP64
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2705 first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first));
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2706 second = _int_0_scope_value;
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2707 # else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2708 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2709 // %%% This is probably a waste but we'll keep things as they were for now
a61af66fc99e Initial load
duke
parents:
diff changeset
2710 if (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2711 VMReg rname_second = rname_first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
2712 second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
a61af66fc99e Initial load
duke
parents:
diff changeset
2713 }
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2714 # endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2715 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2716
a61af66fc99e Initial load
duke
parents:
diff changeset
2717 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2718 // On SPARC, fpu_regnrLo/fpu_regnrHi represents the two halves of
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2719 // the double as float registers in the native ordering. On X86,
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2720 // fpu_regnrLo is a FPU stack slot whose VMReg represents
a61af66fc99e Initial load
duke
parents:
diff changeset
2721 // the low-order word of the double and fpu_regnrLo + 1 is the
a61af66fc99e Initial load
duke
parents:
diff changeset
2722 // name for the other half. *first and *second must represent the
a61af66fc99e Initial load
duke
parents:
diff changeset
2723 // least and most significant words, respectively.
a61af66fc99e Initial load
duke
parents:
diff changeset
2724
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2725 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2726 // the exact location of fpu stack values is only known
a61af66fc99e Initial load
duke
parents:
diff changeset
2727 // during fpu stack allocation, so the stack allocator object
a61af66fc99e Initial load
duke
parents:
diff changeset
2728 // must be present
a61af66fc99e Initial load
duke
parents:
diff changeset
2729 assert(use_fpu_stack_allocation(), "should not have float stack values without fpu stack allocation (all floats must be SSE2)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2730 assert(_fpu_stack_allocator != NULL, "must be present");
a61af66fc99e Initial load
duke
parents:
diff changeset
2731 opr = _fpu_stack_allocator->to_fpu_stack(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2732
2345
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2733 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrLo is used)");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2734 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2735 #ifdef SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
2736 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi() + 1, "assumed in calculation (only fpu_regnrHi is used)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2737 #endif
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2738 #ifdef ARM
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2739 assert(opr->fpu_regnrHi() == opr->fpu_regnrLo() + 1, "assumed in calculation (only fpu_regnrLo is used)");
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2740 #endif
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2741 #ifdef PPC
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2742 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrHi is used)");
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2743 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2744
2345
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2745 #ifdef VM_LITTLE_ENDIAN
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2746 VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrLo());
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2747 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2748 VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrHi());
2345
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2749 #endif
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2750
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2751 #ifdef _LP64
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2752 first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first));
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2753 second = _int_0_scope_value;
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2754 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2755 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2756 // %%% This is probably a waste but we'll keep things as they were for now
a61af66fc99e Initial load
duke
parents:
diff changeset
2757 if (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2758 VMReg rname_second = rname_first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
2759 second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
a61af66fc99e Initial load
duke
parents:
diff changeset
2760 }
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2761 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2762
a61af66fc99e Initial load
duke
parents:
diff changeset
2763 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2764 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2765 first = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2766 second = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2767 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2768
a61af66fc99e Initial load
duke
parents:
diff changeset
2769 assert(first != NULL && second != NULL, "must be set");
a61af66fc99e Initial load
duke
parents:
diff changeset
2770 // The convention the interpreter uses is that the second local
a61af66fc99e Initial load
duke
parents:
diff changeset
2771 // holds the first raw word of the native double representation.
a61af66fc99e Initial load
duke
parents:
diff changeset
2772 // This is actually reasonable, since locals and stack arrays
a61af66fc99e Initial load
duke
parents:
diff changeset
2773 // grow downwards in all implementations.
a61af66fc99e Initial load
duke
parents:
diff changeset
2774 // (If, on some machine, the interpreter's Java locals or stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2775 // were to grow upwards, the embedded doubles would be word-swapped.)
a61af66fc99e Initial load
duke
parents:
diff changeset
2776 scope_values->append(second);
a61af66fc99e Initial load
duke
parents:
diff changeset
2777 scope_values->append(first);
a61af66fc99e Initial load
duke
parents:
diff changeset
2778 return 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2779 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2780 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2781
a61af66fc99e Initial load
duke
parents:
diff changeset
2782
a61af66fc99e Initial load
duke
parents:
diff changeset
2783 int LinearScan::append_scope_value(int op_id, Value value, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2784 if (value != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2785 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
2786 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
2787
a61af66fc99e Initial load
duke
parents:
diff changeset
2788 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)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2789 assert(con != NULL || opr->is_virtual(), "asumption: non-Constant instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2790
a61af66fc99e Initial load
duke
parents:
diff changeset
2791 if (con != NULL && !con->is_pinned() && !opr->is_constant()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2792 // Unpinned constants may have a virtual operand for a part of the lifetime
a61af66fc99e Initial load
duke
parents:
diff changeset
2793 // or may be illegal when it was optimized away,
a61af66fc99e Initial load
duke
parents:
diff changeset
2794 // so always use a constant operand
a61af66fc99e Initial load
duke
parents:
diff changeset
2795 opr = LIR_OprFact::value_type(con->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
2796 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2797 assert(opr->is_virtual() || opr->is_constant(), "other cases not allowed here");
a61af66fc99e Initial load
duke
parents:
diff changeset
2798
a61af66fc99e Initial load
duke
parents:
diff changeset
2799 if (opr->is_virtual()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2800 LIR_OpVisitState::OprMode mode = LIR_OpVisitState::inputMode;
a61af66fc99e Initial load
duke
parents:
diff changeset
2801
a61af66fc99e Initial load
duke
parents:
diff changeset
2802 BlockBegin* block = block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2803 if (block->number_of_sux() == 1 && op_id == block->last_lir_instruction_id()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2804 // generating debug information for the last instruction of a block.
a61af66fc99e Initial load
duke
parents:
diff changeset
2805 // if this instruction is a branch, spill moves are inserted before this branch
a61af66fc99e Initial load
duke
parents:
diff changeset
2806 // and so the wrong operand would be returned (spill moves at block boundaries are not
a61af66fc99e Initial load
duke
parents:
diff changeset
2807 // considered in the live ranges of intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
2808 // Solution: use the first op_id of the branch target block instead.
a61af66fc99e Initial load
duke
parents:
diff changeset
2809 if (block->lir()->instructions_list()->last()->as_OpBranch() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2810 if (block->live_out().at(opr->vreg_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2811 op_id = block->sux_at(0)->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
2812 mode = LIR_OpVisitState::outputMode;
a61af66fc99e Initial load
duke
parents:
diff changeset
2813 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2814 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2816
a61af66fc99e Initial load
duke
parents:
diff changeset
2817 // Get current location of operand
a61af66fc99e Initial load
duke
parents:
diff changeset
2818 // The operand must be live because debug information is considered when building the intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
2819 // if the interval is not live, color_lir_opr will cause an assertion failure
a61af66fc99e Initial load
duke
parents:
diff changeset
2820 opr = color_lir_opr(opr, op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2821 assert(!has_call(op_id) || opr->is_stack() || !is_caller_save(reg_num(opr)), "can not have caller-save register operands at calls");
a61af66fc99e Initial load
duke
parents:
diff changeset
2822
a61af66fc99e Initial load
duke
parents:
diff changeset
2823 // Append to ScopeValue array
a61af66fc99e Initial load
duke
parents:
diff changeset
2824 return append_scope_value_for_operand(opr, scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
2825
a61af66fc99e Initial load
duke
parents:
diff changeset
2826 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2827 assert(value->as_Constant() != NULL, "all other instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2828 assert(opr->is_constant(), "operand must be constant");
a61af66fc99e Initial load
duke
parents:
diff changeset
2829
a61af66fc99e Initial load
duke
parents:
diff changeset
2830 return append_scope_value_for_constant(opr, scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
2831 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2832 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2833 // append a dummy value because real value not needed
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2834 scope_values->append(_illegal_value);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2835 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2836 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2837 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2838
a61af66fc99e Initial load
duke
parents:
diff changeset
2839
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2840 IRScopeDebugInfo* LinearScan::compute_debug_info_for_scope(int op_id, IRScope* cur_scope, ValueStack* cur_state, ValueStack* innermost_state) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2841 IRScopeDebugInfo* caller_debug_info = NULL;
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2842
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2843 ValueStack* caller_state = cur_state->caller_state();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2844 if (caller_state != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2845 // process recursively to compute outermost scope first
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2846 caller_debug_info = compute_debug_info_for_scope(op_id, cur_scope->caller(), caller_state, innermost_state);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2847 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2848
a61af66fc99e Initial load
duke
parents:
diff changeset
2849 // initialize these to null.
a61af66fc99e Initial load
duke
parents:
diff changeset
2850 // If we don't need deopt info or there are no locals, expressions or monitors,
a61af66fc99e Initial load
duke
parents:
diff changeset
2851 // then these get recorded as no information and avoids the allocation of 0 length arrays.
a61af66fc99e Initial load
duke
parents:
diff changeset
2852 GrowableArray<ScopeValue*>* locals = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2853 GrowableArray<ScopeValue*>* expressions = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2854 GrowableArray<MonitorValue*>* monitors = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2855
a61af66fc99e Initial load
duke
parents:
diff changeset
2856 // describe local variable values
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2857 int nof_locals = cur_state->locals_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2858 if (nof_locals > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2859 locals = new GrowableArray<ScopeValue*>(nof_locals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2860
a61af66fc99e Initial load
duke
parents:
diff changeset
2861 int pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2862 while (pos < nof_locals) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2863 assert(pos < cur_state->locals_size(), "why not?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2864
a61af66fc99e Initial load
duke
parents:
diff changeset
2865 Value local = cur_state->local_at(pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
2866 pos += append_scope_value(op_id, local, locals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2867
a61af66fc99e Initial load
duke
parents:
diff changeset
2868 assert(locals->length() == pos, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
2869 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2870 assert(locals->length() == cur_scope->method()->max_locals(), "wrong number of locals");
a61af66fc99e Initial load
duke
parents:
diff changeset
2871 assert(locals->length() == cur_state->locals_size(), "wrong number of locals");
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2872 } else if (cur_scope->method()->max_locals() > 0) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2873 assert(cur_state->kind() == ValueStack::EmptyExceptionState, "should be");
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2874 nof_locals = cur_scope->method()->max_locals();
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2875 locals = new GrowableArray<ScopeValue*>(nof_locals);
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2876 for(int i = 0; i < nof_locals; i++) {
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2877 locals->append(_illegal_value);
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2878 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2879 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2880
a61af66fc99e Initial load
duke
parents:
diff changeset
2881 // describe expression stack
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2882 int nof_stack = cur_state->stack_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2883 if (nof_stack > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2884 expressions = new GrowableArray<ScopeValue*>(nof_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
2885
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2886 int pos = 0;
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2887 while (pos < nof_stack) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2888 Value expression = cur_state->stack_at_inc(pos);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2889 append_scope_value(op_id, expression, expressions);
a61af66fc99e Initial load
duke
parents:
diff changeset
2890
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2891 assert(expressions->length() == pos, "must match");
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2892 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2893 assert(expressions->length() == cur_state->stack_size(), "wrong number of stack entries");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2894 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2895
a61af66fc99e Initial load
duke
parents:
diff changeset
2896 // describe monitors
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2897 int nof_locks = cur_state->locks_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2898 if (nof_locks > 0) {
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2899 int lock_offset = cur_state->caller_state() != NULL ? cur_state->caller_state()->total_locks_size() : 0;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2900 monitors = new GrowableArray<MonitorValue*>(nof_locks);
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2901 for (int i = 0; i < nof_locks; i++) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2902 monitors->append(location_for_monitor_index(lock_offset + i));
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2903 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2904 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2905
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2906 return new IRScopeDebugInfo(cur_scope, cur_state->bci(), locals, expressions, monitors, caller_debug_info);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2907 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2908
a61af66fc99e Initial load
duke
parents:
diff changeset
2909
a61af66fc99e Initial load
duke
parents:
diff changeset
2910 void LinearScan::compute_debug_info(CodeEmitInfo* info, int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2911 TRACE_LINEAR_SCAN(3, tty->print_cr("creating debug information at op_id %d", op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
2912
a61af66fc99e Initial load
duke
parents:
diff changeset
2913 IRScope* innermost_scope = info->scope();
a61af66fc99e Initial load
duke
parents:
diff changeset
2914 ValueStack* innermost_state = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
2915
a61af66fc99e Initial load
duke
parents:
diff changeset
2916 assert(innermost_scope != NULL && innermost_state != NULL, "why is it missing?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2917
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2918 DEBUG_ONLY(check_stack_depth(info, innermost_state->stack_size()));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2919
a61af66fc99e Initial load
duke
parents:
diff changeset
2920 if (info->_scope_debug_info == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2921 // compute debug information
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2922 info->_scope_debug_info = compute_debug_info_for_scope(op_id, innermost_scope, innermost_state, innermost_state);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2923 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2924 // debug information already set. Check that it is correct from the current point of view
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2925 DEBUG_ONLY(assert_equal(info->_scope_debug_info, compute_debug_info_for_scope(op_id, innermost_scope, innermost_state, innermost_state)));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2926 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2927 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2928
a61af66fc99e Initial load
duke
parents:
diff changeset
2929
a61af66fc99e Initial load
duke
parents:
diff changeset
2930 void LinearScan::assign_reg_num(LIR_OpList* instructions, IntervalWalker* iw) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2931 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
2932 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2933 bool has_dead = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
2934
a61af66fc99e Initial load
duke
parents:
diff changeset
2935 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2936 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
2937 if (op == NULL) { // this can happen when spill-moves are removed in eliminate_spill_moves
a61af66fc99e Initial load
duke
parents:
diff changeset
2938 has_dead = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
2939 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
2940 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2941 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
2942
a61af66fc99e Initial load
duke
parents:
diff changeset
2943 // visit instruction to get list of operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2944 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2945
a61af66fc99e Initial load
duke
parents:
diff changeset
2946 // iterate all modes of the visitor and process all virtual operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2947 for_each_visitor_mode(mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2948 int n = visitor.opr_count(mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2949 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2950 LIR_Opr opr = visitor.opr_at(mode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
2951 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2952 visitor.set_opr_at(mode, k, color_lir_opr(opr, op_id, mode));
a61af66fc99e Initial load
duke
parents:
diff changeset
2953 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2954 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2955 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2956
a61af66fc99e Initial load
duke
parents:
diff changeset
2957 if (visitor.info_count() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2958 // exception handling
a61af66fc99e Initial load
duke
parents:
diff changeset
2959 if (compilation()->has_exception_handlers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2960 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
2961 int n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2962 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2963 XHandler* handler = xhandlers->handler_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
2964 if (handler->entry_code() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2965 assign_reg_num(handler->entry_code()->instructions_list(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2966 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2967 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2968 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2969 assert(visitor.all_xhandler()->length() == 0, "missed exception handler");
a61af66fc99e Initial load
duke
parents:
diff changeset
2970 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2971
a61af66fc99e Initial load
duke
parents:
diff changeset
2972 // compute oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2973 assert(iw != NULL, "needed for compute_oop_map");
a61af66fc99e Initial load
duke
parents:
diff changeset
2974 compute_oop_map(iw, visitor, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2975
a61af66fc99e Initial load
duke
parents:
diff changeset
2976 // compute debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
2977 if (!use_fpu_stack_allocation()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2978 // compute debug information if fpu stack allocation is not needed.
a61af66fc99e Initial load
duke
parents:
diff changeset
2979 // when fpu stack allocation is needed, the debug information can not
a61af66fc99e Initial load
duke
parents:
diff changeset
2980 // be computed here because the exact location of fpu operands is not known
a61af66fc99e Initial load
duke
parents:
diff changeset
2981 // -> debug information is created inside the fpu stack allocator
a61af66fc99e Initial load
duke
parents:
diff changeset
2982 int n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
2983 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2984 compute_debug_info(visitor.info_at(k), op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2985 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2986 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2987 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2988
a61af66fc99e Initial load
duke
parents:
diff changeset
2989 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2990 // make sure we haven't made the op invalid.
a61af66fc99e Initial load
duke
parents:
diff changeset
2991 op->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
2992 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2993
a61af66fc99e Initial load
duke
parents:
diff changeset
2994 // remove useless moves
a61af66fc99e Initial load
duke
parents:
diff changeset
2995 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2996 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
2997 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
2998 LIR_Opr src = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2999 LIR_Opr dst = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3000 if (dst == src ||
a61af66fc99e Initial load
duke
parents:
diff changeset
3001 !dst->is_pointer() && !src->is_pointer() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
3002 src->is_same_register(dst)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3003 instructions->at_put(j, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3004 has_dead = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3005 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3006 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3007 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3008
a61af66fc99e Initial load
duke
parents:
diff changeset
3009 if (has_dead) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3010 // iterate all instructions of the block and remove all null-values.
a61af66fc99e Initial load
duke
parents:
diff changeset
3011 int insert_point = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
3012 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3013 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3014 if (op != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3015 if (insert_point != j) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3016 instructions->at_put(insert_point, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3017 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3018 insert_point++;
a61af66fc99e Initial load
duke
parents:
diff changeset
3019 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3020 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3021 instructions->truncate(insert_point);
a61af66fc99e Initial load
duke
parents:
diff changeset
3022 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3023 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3024
a61af66fc99e Initial load
duke
parents:
diff changeset
3025 void LinearScan::assign_reg_num() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3026 TIME_LINEAR_SCAN(timer_assign_reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
3027
a61af66fc99e Initial load
duke
parents:
diff changeset
3028 init_compute_debug_info();
a61af66fc99e Initial load
duke
parents:
diff changeset
3029 IntervalWalker* iw = init_compute_oop_maps();
a61af66fc99e Initial load
duke
parents:
diff changeset
3030
a61af66fc99e Initial load
duke
parents:
diff changeset
3031 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3032 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3033 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3034 assign_reg_num(block->lir()->instructions_list(), iw);
a61af66fc99e Initial load
duke
parents:
diff changeset
3035 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3036 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3037
a61af66fc99e Initial load
duke
parents:
diff changeset
3038
a61af66fc99e Initial load
duke
parents:
diff changeset
3039 void LinearScan::do_linear_scan() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3040 NOT_PRODUCT(_total_timer.begin_method());
a61af66fc99e Initial load
duke
parents:
diff changeset
3041
a61af66fc99e Initial load
duke
parents:
diff changeset
3042 number_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
3043
a61af66fc99e Initial load
duke
parents:
diff changeset
3044 NOT_PRODUCT(print_lir(1, "Before Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3045
a61af66fc99e Initial load
duke
parents:
diff changeset
3046 compute_local_live_sets();
a61af66fc99e Initial load
duke
parents:
diff changeset
3047 compute_global_live_sets();
a61af66fc99e Initial load
duke
parents:
diff changeset
3048 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3049
a61af66fc99e Initial load
duke
parents:
diff changeset
3050 build_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3051 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3052 sort_intervals_before_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
3053
a61af66fc99e Initial load
duke
parents:
diff changeset
3054 NOT_PRODUCT(print_intervals("Before Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3055 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_before_alloc));
a61af66fc99e Initial load
duke
parents:
diff changeset
3056
a61af66fc99e Initial load
duke
parents:
diff changeset
3057 allocate_registers();
a61af66fc99e Initial load
duke
parents:
diff changeset
3058 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3059
a61af66fc99e Initial load
duke
parents:
diff changeset
3060 resolve_data_flow();
a61af66fc99e Initial load
duke
parents:
diff changeset
3061 if (compilation()->has_exception_handlers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3062 resolve_exception_handlers();
a61af66fc99e Initial load
duke
parents:
diff changeset
3063 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3064 // fill in number of spill slots into frame_map
a61af66fc99e Initial load
duke
parents:
diff changeset
3065 propagate_spill_slots();
a61af66fc99e Initial load
duke
parents:
diff changeset
3066 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3067
a61af66fc99e Initial load
duke
parents:
diff changeset
3068 NOT_PRODUCT(print_intervals("After Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3069 NOT_PRODUCT(print_lir(2, "LIR after register allocation:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3070
a61af66fc99e Initial load
duke
parents:
diff changeset
3071 sort_intervals_after_allocation();
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3072
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3073 DEBUG_ONLY(verify());
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3074
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3075 eliminate_spill_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
3076 assign_reg_num();
a61af66fc99e Initial load
duke
parents:
diff changeset
3077 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3078
a61af66fc99e Initial load
duke
parents:
diff changeset
3079 NOT_PRODUCT(print_lir(2, "LIR after assignment of register numbers:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3080 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_after_asign));
a61af66fc99e Initial load
duke
parents:
diff changeset
3081
a61af66fc99e Initial load
duke
parents:
diff changeset
3082 { TIME_LINEAR_SCAN(timer_allocate_fpu_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
3083
a61af66fc99e Initial load
duke
parents:
diff changeset
3084 if (use_fpu_stack_allocation()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3085 allocate_fpu_stack(); // Only has effect on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
3086 NOT_PRODUCT(print_lir(2, "LIR after FPU stack allocation:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3087 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3088 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3089
a61af66fc99e Initial load
duke
parents:
diff changeset
3090 { TIME_LINEAR_SCAN(timer_optimize_lir);
a61af66fc99e Initial load
duke
parents:
diff changeset
3091
a61af66fc99e Initial load
duke
parents:
diff changeset
3092 EdgeMoveOptimizer::optimize(ir()->code());
a61af66fc99e Initial load
duke
parents:
diff changeset
3093 ControlFlowOptimizer::optimize(ir()->code());
a61af66fc99e Initial load
duke
parents:
diff changeset
3094 // check that cfg is still correct after optimizations
a61af66fc99e Initial load
duke
parents:
diff changeset
3095 ir()->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
3096 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3097
a61af66fc99e Initial load
duke
parents:
diff changeset
3098 NOT_PRODUCT(print_lir(1, "Before Code Generation", false));
a61af66fc99e Initial load
duke
parents:
diff changeset
3099 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_final));
a61af66fc99e Initial load
duke
parents:
diff changeset
3100 NOT_PRODUCT(_total_timer.end_method(this));
a61af66fc99e Initial load
duke
parents:
diff changeset
3101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3102
a61af66fc99e Initial load
duke
parents:
diff changeset
3103
a61af66fc99e Initial load
duke
parents:
diff changeset
3104 // ********** Printing functions
a61af66fc99e Initial load
duke
parents:
diff changeset
3105
a61af66fc99e Initial load
duke
parents:
diff changeset
3106 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
3107
a61af66fc99e Initial load
duke
parents:
diff changeset
3108 void LinearScan::print_timers(double total) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3109 _total_timer.print(total);
a61af66fc99e Initial load
duke
parents:
diff changeset
3110 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3111
a61af66fc99e Initial load
duke
parents:
diff changeset
3112 void LinearScan::print_statistics() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3113 _stat_before_alloc.print("before allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
3114 _stat_after_asign.print("after assignment of register");
a61af66fc99e Initial load
duke
parents:
diff changeset
3115 _stat_final.print("after optimization");
a61af66fc99e Initial load
duke
parents:
diff changeset
3116 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3117
a61af66fc99e Initial load
duke
parents:
diff changeset
3118 void LinearScan::print_bitmap(BitMap& b) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3119 for (unsigned int i = 0; i < b.size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3120 if (b.at(i)) tty->print("%d ", i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3121 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3122 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3123 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3124
a61af66fc99e Initial load
duke
parents:
diff changeset
3125 void LinearScan::print_intervals(const char* label) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3126 if (TraceLinearScanLevel >= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3127 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3128 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3129 tty->print_cr("%s", label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3130
a61af66fc99e Initial load
duke
parents:
diff changeset
3131 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3132 Interval* interval = interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3133 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3134 interval->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
3135 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3137
a61af66fc99e Initial load
duke
parents:
diff changeset
3138 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3139 tty->print_cr("--- Basic Blocks ---");
a61af66fc99e Initial load
duke
parents:
diff changeset
3140 for (i = 0; i < block_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3141 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3142 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());
a61af66fc99e Initial load
duke
parents:
diff changeset
3143 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3144 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3145 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3147
a61af66fc99e Initial load
duke
parents:
diff changeset
3148 if (PrintCFGToFile) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3149 CFGPrinter::print_intervals(&_intervals, label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3150 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3151 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3152
a61af66fc99e Initial load
duke
parents:
diff changeset
3153 void LinearScan::print_lir(int level, const char* label, bool hir_valid) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3154 if (TraceLinearScanLevel >= level) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3155 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3156 tty->print_cr("%s", label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3157 print_LIR(ir()->linear_scan_order());
a61af66fc99e Initial load
duke
parents:
diff changeset
3158 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3159 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3160
a61af66fc99e Initial load
duke
parents:
diff changeset
3161 if (level == 1 && PrintCFGToFile) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3162 CFGPrinter::print_cfg(ir()->linear_scan_order(), label, hir_valid, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
3163 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3164 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3165
a61af66fc99e Initial load
duke
parents:
diff changeset
3166 #endif //PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
3167
a61af66fc99e Initial load
duke
parents:
diff changeset
3168
a61af66fc99e Initial load
duke
parents:
diff changeset
3169 // ********** verification functions for allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
3170 // (check that all intervals have a correct register and that no registers are overwritten)
a61af66fc99e Initial load
duke
parents:
diff changeset
3171 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3172
a61af66fc99e Initial load
duke
parents:
diff changeset
3173 void LinearScan::verify() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3174 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying intervals ******************************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3175 verify_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3176
a61af66fc99e Initial load
duke
parents:
diff changeset
3177 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying that no oops are in fixed intervals ****************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3178 verify_no_oops_in_fixed_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3179
a61af66fc99e Initial load
duke
parents:
diff changeset
3180 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying that unpinned constants are not alive across block boundaries"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3181 verify_constants();
a61af66fc99e Initial load
duke
parents:
diff changeset
3182
a61af66fc99e Initial load
duke
parents:
diff changeset
3183 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying register allocation ********************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3184 verify_registers();
a61af66fc99e Initial load
duke
parents:
diff changeset
3185
a61af66fc99e Initial load
duke
parents:
diff changeset
3186 TRACE_LINEAR_SCAN(2, tty->print_cr("********* no errors found **********************************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3187 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3188
a61af66fc99e Initial load
duke
parents:
diff changeset
3189 void LinearScan::verify_intervals() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3190 int len = interval_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3191 bool has_error = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3192
a61af66fc99e Initial load
duke
parents:
diff changeset
3193 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3194 Interval* i1 = interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3195 if (i1 == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3196
a61af66fc99e Initial load
duke
parents:
diff changeset
3197 i1->check_split_children();
a61af66fc99e Initial load
duke
parents:
diff changeset
3198
a61af66fc99e Initial load
duke
parents:
diff changeset
3199 if (i1->reg_num() != i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3200 tty->print_cr("Interval %d is on position %d in list", i1->reg_num(), i); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3201 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3203
a61af66fc99e Initial load
duke
parents:
diff changeset
3204 if (i1->reg_num() >= LIR_OprDesc::vreg_base && i1->type() == T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3205 tty->print_cr("Interval %d has no type assigned", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3206 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3207 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3208
a61af66fc99e Initial load
duke
parents:
diff changeset
3209 if (i1->assigned_reg() == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3210 tty->print_cr("Interval %d has no register assigned", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3211 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3212 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3213
a61af66fc99e Initial load
duke
parents:
diff changeset
3214 if (i1->assigned_reg() == i1->assigned_regHi()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3215 tty->print_cr("Interval %d: low and high register equal", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3216 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3217 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3218
a61af66fc99e Initial load
duke
parents:
diff changeset
3219 if (!is_processed_reg_num(i1->assigned_reg())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3220 tty->print_cr("Can not have an Interval for an ignored register"); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3221 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3222 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3223
a61af66fc99e Initial load
duke
parents:
diff changeset
3224 if (i1->first() == Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3225 tty->print_cr("Interval %d has no Range", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3226 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3227 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3228
a61af66fc99e Initial load
duke
parents:
diff changeset
3229 for (Range* r = i1->first(); r != Range::end(); r = r->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3230 if (r->from() >= r->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3231 tty->print_cr("Interval %d has zero length range", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3232 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3233 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3234 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3235
a61af66fc99e Initial load
duke
parents:
diff changeset
3236 for (int j = i + 1; j < len; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3237 Interval* i2 = interval_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3238 if (i2 == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3239
a61af66fc99e Initial load
duke
parents:
diff changeset
3240 // special intervals that are created in MoveResolver
a61af66fc99e Initial load
duke
parents:
diff changeset
3241 // -> ignore them because the range information has no meaning there
a61af66fc99e Initial load
duke
parents:
diff changeset
3242 if (i1->from() == 1 && i1->to() == 2) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3243 if (i2->from() == 1 && i2->to() == 2) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3244
a61af66fc99e Initial load
duke
parents:
diff changeset
3245 int r1 = i1->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3246 int r1Hi = i1->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3247 int r2 = i2->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3248 int r2Hi = i2->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3249 if (i1->intersects(i2) && (r1 == r2 || r1 == r2Hi || (r1Hi != any_reg && (r1Hi == r2 || r1Hi == r2Hi)))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3250 tty->print_cr("Intervals %d and %d overlap and have the same register assigned", i1->reg_num(), i2->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
3251 i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3252 i2->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3253 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3254 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3255 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3256 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3257
a61af66fc99e Initial load
duke
parents:
diff changeset
3258 assert(has_error == false, "register allocation invalid");
a61af66fc99e Initial load
duke
parents:
diff changeset
3259 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3260
a61af66fc99e Initial load
duke
parents:
diff changeset
3261
a61af66fc99e Initial load
duke
parents:
diff changeset
3262 void LinearScan::verify_no_oops_in_fixed_intervals() {
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3263 Interval* fixed_intervals;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3264 Interval* other_intervals;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3265 create_unhandled_lists(&fixed_intervals, &other_intervals, is_precolored_cpu_interval, NULL);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3266
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3267 // to ensure a walking until the last instruction id, add a dummy interval
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3268 // with a high operation id
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3269 other_intervals = new Interval(any_reg);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3270 other_intervals->add_range(max_jint - 2, max_jint - 1);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3271 IntervalWalker* iw = new IntervalWalker(this, fixed_intervals, other_intervals);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3272
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3273 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
3274 for (int i = 0; i < block_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3275 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3276
a61af66fc99e Initial load
duke
parents:
diff changeset
3277 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
3278
a61af66fc99e Initial load
duke
parents:
diff changeset
3279 for (int j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3280 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3281 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
3282
a61af66fc99e Initial load
duke
parents:
diff changeset
3283 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3284
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3285 if (visitor.info_count() > 0) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3286 iw->walk_before(op->id());
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3287 bool check_live = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3288 if (op->code() == lir_move) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3289 LIR_Op1* move = (LIR_Op1*)op;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3290 check_live = (move->patch_code() == lir_patch_none);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3291 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3292 LIR_OpBranch* branch = op->as_OpBranch();
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3293 if (branch != NULL && branch->stub() != NULL && branch->stub()->is_exception_throw_stub()) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3294 // Don't bother checking the stub in this case since the
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3295 // exception stub will never return to normal control flow.
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3296 check_live = false;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3297 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3298
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3299 // Make sure none of the fixed registers is live across an
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3300 // oopmap since we can't handle that correctly.
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3301 if (check_live) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3302 for (Interval* interval = iw->active_first(fixedKind);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3303 interval != Interval::end();
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3304 interval = interval->next()) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3305 if (interval->current_to() > op->id() + 1) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3306 // This interval is live out of this op so make sure
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3307 // that this interval represents some value that's
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3308 // referenced by this op either as an input or output.
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3309 bool ok = false;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3310 for_each_visitor_mode(mode) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3311 int n = visitor.opr_count(mode);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3312 for (int k = 0; k < n; k++) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3313 LIR_Opr opr = visitor.opr_at(mode, k);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3314 if (opr->is_fixed_cpu()) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3315 if (interval_at(reg_num(opr)) == interval) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3316 ok = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3317 break;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3318 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3319 int hi = reg_numHi(opr);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3320 if (hi != -1 && interval_at(hi) == interval) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3321 ok = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3322 break;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3323 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3324 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3325 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3326 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3327 assert(ok, "fixed intervals should never be live across an oopmap point");
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3328 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3329 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3330 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3331 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3332
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3333 // oop-maps at calls do not contain registers, so check is not needed
a61af66fc99e Initial load
duke
parents:
diff changeset
3334 if (!visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3335
a61af66fc99e Initial load
duke
parents:
diff changeset
3336 for_each_visitor_mode(mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3337 int n = visitor.opr_count(mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3338 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3339 LIR_Opr opr = visitor.opr_at(mode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
3340
a61af66fc99e Initial load
duke
parents:
diff changeset
3341 if (opr->is_fixed_cpu() && opr->is_oop()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3342 // operand is a non-virtual cpu register and contains an oop
a61af66fc99e Initial load
duke
parents:
diff changeset
3343 TRACE_LINEAR_SCAN(4, op->print_on(tty); tty->print("checking operand "); opr->print(); tty->cr());
a61af66fc99e Initial load
duke
parents:
diff changeset
3344
a61af66fc99e Initial load
duke
parents:
diff changeset
3345 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3346 assert(interval != NULL, "no interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
3347
a61af66fc99e Initial load
duke
parents:
diff changeset
3348 if (mode == LIR_OpVisitState::inputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3349 if (interval->to() >= op_id + 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3350 assert(interval->to() < op_id + 2 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
3351 interval->has_hole_between(op_id, op_id + 2),
a61af66fc99e Initial load
duke
parents:
diff changeset
3352 "oop input operand live after instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
3353 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3354 } else if (mode == LIR_OpVisitState::outputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3355 if (interval->from() <= op_id - 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3356 assert(interval->has_hole_between(op_id - 1, op_id),
a61af66fc99e Initial load
duke
parents:
diff changeset
3357 "oop input operand live after instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
3358 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3359 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3360 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3361 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3362 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3363 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3364 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3365 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3366 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3367
a61af66fc99e Initial load
duke
parents:
diff changeset
3368
a61af66fc99e Initial load
duke
parents:
diff changeset
3369 void LinearScan::verify_constants() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3370 int num_regs = num_virtual_regs();
a61af66fc99e Initial load
duke
parents:
diff changeset
3371 int size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
3372 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3373
a61af66fc99e Initial load
duke
parents:
diff changeset
3374 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3375 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3376 BitMap live_at_edge = block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
3377
a61af66fc99e Initial load
duke
parents:
diff changeset
3378 // visit all registers where the live_at_edge bit is set
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
3379 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)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3380 TRACE_LINEAR_SCAN(4, tty->print("checking interval %d of block B%d", r, block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3381
a61af66fc99e Initial load
duke
parents:
diff changeset
3382 Value value = gen()->instruction_for_vreg(r);
a61af66fc99e Initial load
duke
parents:
diff changeset
3383
a61af66fc99e Initial load
duke
parents:
diff changeset
3384 assert(value != NULL, "all intervals live across block boundaries must have Value");
a61af66fc99e Initial load
duke
parents:
diff changeset
3385 assert(value->operand()->is_register() && value->operand()->is_virtual(), "value must have virtual operand");
a61af66fc99e Initial load
duke
parents:
diff changeset
3386 assert(value->operand()->vreg_number() == r, "register number must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
3387 // TKR assert(value->as_Constant() == NULL || value->is_pinned(), "only pinned constants can be alive accross block boundaries");
a61af66fc99e Initial load
duke
parents:
diff changeset
3388 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3389 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3390 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3391
a61af66fc99e Initial load
duke
parents:
diff changeset
3392
a61af66fc99e Initial load
duke
parents:
diff changeset
3393 class RegisterVerifier: public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
3394 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
3395 LinearScan* _allocator;
a61af66fc99e Initial load
duke
parents:
diff changeset
3396 BlockList _work_list; // all blocks that must be processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3397 IntervalsList _saved_states; // saved information of previous check
a61af66fc99e Initial load
duke
parents:
diff changeset
3398
a61af66fc99e Initial load
duke
parents:
diff changeset
3399 // simplified access to methods of LinearScan
a61af66fc99e Initial load
duke
parents:
diff changeset
3400 Compilation* compilation() const { return _allocator->compilation(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3401 Interval* interval_at(int reg_num) const { return _allocator->interval_at(reg_num); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3402 int reg_num(LIR_Opr opr) const { return _allocator->reg_num(opr); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3403
a61af66fc99e Initial load
duke
parents:
diff changeset
3404 // currently, only registers are processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3405 int state_size() { return LinearScan::nof_regs; }
a61af66fc99e Initial load
duke
parents:
diff changeset
3406
a61af66fc99e Initial load
duke
parents:
diff changeset
3407 // accessors
a61af66fc99e Initial load
duke
parents:
diff changeset
3408 IntervalList* state_for_block(BlockBegin* block) { return _saved_states.at(block->block_id()); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3409 void set_state_for_block(BlockBegin* block, IntervalList* saved_state) { _saved_states.at_put(block->block_id(), saved_state); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3410 void add_to_work_list(BlockBegin* block) { if (!_work_list.contains(block)) _work_list.append(block); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3411
a61af66fc99e Initial load
duke
parents:
diff changeset
3412 // helper functions
a61af66fc99e Initial load
duke
parents:
diff changeset
3413 IntervalList* copy(IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3414 void state_put(IntervalList* input_state, int reg, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3415 bool check_state(IntervalList* input_state, int reg, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3416
a61af66fc99e Initial load
duke
parents:
diff changeset
3417 void process_block(BlockBegin* block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3418 void process_xhandler(XHandler* xhandler, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3419 void process_successor(BlockBegin* block, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3420 void process_operations(LIR_List* ops, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3421
a61af66fc99e Initial load
duke
parents:
diff changeset
3422 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
3423 RegisterVerifier(LinearScan* allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
3424 : _allocator(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
3425 , _work_list(16)
a61af66fc99e Initial load
duke
parents:
diff changeset
3426 , _saved_states(BlockBegin::number_of_blocks(), NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
3427 { }
a61af66fc99e Initial load
duke
parents:
diff changeset
3428
a61af66fc99e Initial load
duke
parents:
diff changeset
3429 void verify(BlockBegin* start);
a61af66fc99e Initial load
duke
parents:
diff changeset
3430 };
a61af66fc99e Initial load
duke
parents:
diff changeset
3431
a61af66fc99e Initial load
duke
parents:
diff changeset
3432
a61af66fc99e Initial load
duke
parents:
diff changeset
3433 // entry function from LinearScan that starts the verification
a61af66fc99e Initial load
duke
parents:
diff changeset
3434 void LinearScan::verify_registers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3435 RegisterVerifier verifier(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
3436 verifier.verify(block_at(0));
a61af66fc99e Initial load
duke
parents:
diff changeset
3437 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3438
a61af66fc99e Initial load
duke
parents:
diff changeset
3439
a61af66fc99e Initial load
duke
parents:
diff changeset
3440 void RegisterVerifier::verify(BlockBegin* start) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3441 // setup input registers (method arguments) for first block
a61af66fc99e Initial load
duke
parents:
diff changeset
3442 IntervalList* input_state = new IntervalList(state_size(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3443 CallingConvention* args = compilation()->frame_map()->incoming_arguments();
a61af66fc99e Initial load
duke
parents:
diff changeset
3444 for (int n = 0; n < args->length(); n++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3445 LIR_Opr opr = args->at(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
3446 if (opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3447 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3448
a61af66fc99e Initial load
duke
parents:
diff changeset
3449 if (interval->assigned_reg() < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3450 input_state->at_put(interval->assigned_reg(), interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3451 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3452 if (interval->assigned_regHi() != LinearScan::any_reg && interval->assigned_regHi() < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3453 input_state->at_put(interval->assigned_regHi(), interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3454 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3455 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3456 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3457
a61af66fc99e Initial load
duke
parents:
diff changeset
3458 set_state_for_block(start, input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3459 add_to_work_list(start);
a61af66fc99e Initial load
duke
parents:
diff changeset
3460
a61af66fc99e Initial load
duke
parents:
diff changeset
3461 // main loop for verification
a61af66fc99e Initial load
duke
parents:
diff changeset
3462 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
3463 BlockBegin* block = _work_list.at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
3464 _work_list.remove_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
3465
a61af66fc99e Initial load
duke
parents:
diff changeset
3466 process_block(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3467 } while (!_work_list.is_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3468 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3469
a61af66fc99e Initial load
duke
parents:
diff changeset
3470 void RegisterVerifier::process_block(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3471 TRACE_LINEAR_SCAN(2, tty->cr(); tty->print_cr("process_block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3472
a61af66fc99e Initial load
duke
parents:
diff changeset
3473 // must copy state because it is modified
a61af66fc99e Initial load
duke
parents:
diff changeset
3474 IntervalList* input_state = copy(state_for_block(block));
a61af66fc99e Initial load
duke
parents:
diff changeset
3475
a61af66fc99e Initial load
duke
parents:
diff changeset
3476 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3477 tty->print_cr("Input-State of intervals:");
a61af66fc99e Initial load
duke
parents:
diff changeset
3478 tty->print(" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
3479 for (int i = 0; i < state_size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3480 if (input_state->at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3481 tty->print(" %4d", input_state->at(i)->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
3482 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3483 tty->print(" __");
a61af66fc99e Initial load
duke
parents:
diff changeset
3484 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3485 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3486 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3487 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3489
a61af66fc99e Initial load
duke
parents:
diff changeset
3490 // process all operations of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
3491 process_operations(block->lir(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3492
a61af66fc99e Initial load
duke
parents:
diff changeset
3493 // iterate all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
3494 for (int i = 0; i < block->number_of_sux(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3495 process_successor(block->sux_at(i), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3496 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3497 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3498
a61af66fc99e Initial load
duke
parents:
diff changeset
3499 void RegisterVerifier::process_xhandler(XHandler* xhandler, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3500 TRACE_LINEAR_SCAN(2, tty->print_cr("process_xhandler B%d", xhandler->entry_block()->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3501
a61af66fc99e Initial load
duke
parents:
diff changeset
3502 // must copy state because it is modified
a61af66fc99e Initial load
duke
parents:
diff changeset
3503 input_state = copy(input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3504
a61af66fc99e Initial load
duke
parents:
diff changeset
3505 if (xhandler->entry_code() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3506 process_operations(xhandler->entry_code(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3507 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3508 process_successor(xhandler->entry_block(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3509 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3510
a61af66fc99e Initial load
duke
parents:
diff changeset
3511 void RegisterVerifier::process_successor(BlockBegin* block, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3512 IntervalList* saved_state = state_for_block(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3513
a61af66fc99e Initial load
duke
parents:
diff changeset
3514 if (saved_state != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3515 // this block was already processed before.
a61af66fc99e Initial load
duke
parents:
diff changeset
3516 // check if new input_state is consistent with saved_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3517
a61af66fc99e Initial load
duke
parents:
diff changeset
3518 bool saved_state_correct = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3519 for (int i = 0; i < state_size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3520 if (input_state->at(i) != saved_state->at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3521 // current input_state and previous saved_state assume a different
a61af66fc99e Initial load
duke
parents:
diff changeset
3522 // interval in this register -> assume that this register is invalid
a61af66fc99e Initial load
duke
parents:
diff changeset
3523 if (saved_state->at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3524 // invalidate old calculation only if it assumed that
a61af66fc99e Initial load
duke
parents:
diff changeset
3525 // register was valid. when the register was already invalid,
a61af66fc99e Initial load
duke
parents:
diff changeset
3526 // then the old calculation was correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
3527 saved_state_correct = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3528 saved_state->at_put(i, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3529
a61af66fc99e Initial load
duke
parents:
diff changeset
3530 TRACE_LINEAR_SCAN(4, tty->print_cr("process_successor B%d: invalidating slot %d", block->block_id(), i));
a61af66fc99e Initial load
duke
parents:
diff changeset
3531 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3532 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3533 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3534
a61af66fc99e Initial load
duke
parents:
diff changeset
3535 if (saved_state_correct) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3536 // already processed block with correct input_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3537 TRACE_LINEAR_SCAN(2, tty->print_cr("process_successor B%d: previous visit already correct", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3538 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3539 // must re-visit this block
a61af66fc99e Initial load
duke
parents:
diff changeset
3540 TRACE_LINEAR_SCAN(2, tty->print_cr("process_successor B%d: must re-visit because input state changed", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3541 add_to_work_list(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3542 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3543
a61af66fc99e Initial load
duke
parents:
diff changeset
3544 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3545 // block was not processed before, so set initial input_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3546 TRACE_LINEAR_SCAN(2, tty->print_cr("process_successor B%d: initial visit", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3547
a61af66fc99e Initial load
duke
parents:
diff changeset
3548 set_state_for_block(block, copy(input_state));
a61af66fc99e Initial load
duke
parents:
diff changeset
3549 add_to_work_list(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3550 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3551 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3552
a61af66fc99e Initial load
duke
parents:
diff changeset
3553
a61af66fc99e Initial load
duke
parents:
diff changeset
3554 IntervalList* RegisterVerifier::copy(IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3555 IntervalList* copy_state = new IntervalList(input_state->length());
a61af66fc99e Initial load
duke
parents:
diff changeset
3556 copy_state->push_all(input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3557 return copy_state;
a61af66fc99e Initial load
duke
parents:
diff changeset
3558 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3559
a61af66fc99e Initial load
duke
parents:
diff changeset
3560 void RegisterVerifier::state_put(IntervalList* input_state, int reg, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3561 if (reg != LinearScan::any_reg && reg < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3562 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3563 TRACE_LINEAR_SCAN(4, tty->print_cr(" reg[%d] = %d", reg, interval->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3564 } else if (input_state->at(reg) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3565 TRACE_LINEAR_SCAN(4, tty->print_cr(" reg[%d] = NULL", reg));
a61af66fc99e Initial load
duke
parents:
diff changeset
3566 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3567
a61af66fc99e Initial load
duke
parents:
diff changeset
3568 input_state->at_put(reg, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3569 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3571
a61af66fc99e Initial load
duke
parents:
diff changeset
3572 bool RegisterVerifier::check_state(IntervalList* input_state, int reg, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3573 if (reg != LinearScan::any_reg && reg < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3574 if (input_state->at(reg) != interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3575 tty->print_cr("!! Error in register allocation: register %d does not contain interval %d", reg, interval->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
3576 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3577 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3578 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3579 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3580 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3581
a61af66fc99e Initial load
duke
parents:
diff changeset
3582 void RegisterVerifier::process_operations(LIR_List* ops, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3583 // visit all instructions of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
3584 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
3585 bool has_error = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3586
a61af66fc99e Initial load
duke
parents:
diff changeset
3587 for (int i = 0; i < ops->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3588 LIR_Op* op = ops->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3589 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3590
a61af66fc99e Initial load
duke
parents:
diff changeset
3591 TRACE_LINEAR_SCAN(4, op->print_on(tty));
a61af66fc99e Initial load
duke
parents:
diff changeset
3592
a61af66fc99e Initial load
duke
parents:
diff changeset
3593 // check if input operands are correct
a61af66fc99e Initial load
duke
parents:
diff changeset
3594 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
3595 int n = visitor.opr_count(LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3596 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3597 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3598 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3599 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3600 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3601 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3602 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3603
a61af66fc99e Initial load
duke
parents:
diff changeset
3604 has_error |= check_state(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3605 has_error |= check_state(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3606
a61af66fc99e Initial load
duke
parents:
diff changeset
3607 // When an operand is marked with is_last_use, then the fpu stack allocator
a61af66fc99e Initial load
duke
parents:
diff changeset
3608 // removes the register from the fpu stack -> the register contains no value
a61af66fc99e Initial load
duke
parents:
diff changeset
3609 if (opr->is_last_use()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3610 state_put(input_state, interval->assigned_reg(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3611 state_put(input_state, interval->assigned_regHi(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3612 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3613 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3614 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3615
a61af66fc99e Initial load
duke
parents:
diff changeset
3616 // invalidate all caller save registers at calls
a61af66fc99e Initial load
duke
parents:
diff changeset
3617 if (visitor.has_call()) {
2002
ac637b7220d1 6985015: C1 needs to support compressed oops
iveresov
parents: 1972
diff changeset
3618 for (j = 0; j < FrameMap::nof_caller_save_cpu_regs(); j++) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3619 state_put(input_state, reg_num(FrameMap::caller_save_cpu_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3620 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3621 for (j = 0; j < FrameMap::nof_caller_save_fpu_regs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3622 state_put(input_state, reg_num(FrameMap::caller_save_fpu_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3623 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3624
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
3625 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3626 for (j = 0; j < FrameMap::nof_caller_save_xmm_regs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3627 state_put(input_state, reg_num(FrameMap::caller_save_xmm_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3628 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3629 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
3630 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3631
a61af66fc99e Initial load
duke
parents:
diff changeset
3632 // process xhandler before output and temp operands
a61af66fc99e Initial load
duke
parents:
diff changeset
3633 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
3634 n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
3635 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3636 process_xhandler(xhandlers->handler_at(k), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3637 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3638
a61af66fc99e Initial load
duke
parents:
diff changeset
3639 // set temp operands (some operations use temp operands also as output operands, so can't set them NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
3640 n = visitor.opr_count(LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3641 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3642 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3643 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3644 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3645 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3646 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3647 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3648
a61af66fc99e Initial load
duke
parents:
diff changeset
3649 state_put(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3650 state_put(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3651 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3652 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3653
a61af66fc99e Initial load
duke
parents:
diff changeset
3654 // set output operands
a61af66fc99e Initial load
duke
parents:
diff changeset
3655 n = visitor.opr_count(LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3656 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3657 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3658 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3659 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3660 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3661 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3662 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3663
a61af66fc99e Initial load
duke
parents:
diff changeset
3664 state_put(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3665 state_put(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3666 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3667 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3668 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3669 assert(has_error == false, "Error in register allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
3670 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3671
a61af66fc99e Initial load
duke
parents:
diff changeset
3672 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3673
a61af66fc99e Initial load
duke
parents:
diff changeset
3674
a61af66fc99e Initial load
duke
parents:
diff changeset
3675
a61af66fc99e Initial load
duke
parents:
diff changeset
3676 // **** Implementation of MoveResolver ******************************
a61af66fc99e Initial load
duke
parents:
diff changeset
3677
a61af66fc99e Initial load
duke
parents:
diff changeset
3678 MoveResolver::MoveResolver(LinearScan* allocator) :
a61af66fc99e Initial load
duke
parents:
diff changeset
3679 _allocator(allocator),
a61af66fc99e Initial load
duke
parents:
diff changeset
3680 _multiple_reads_allowed(false),
a61af66fc99e Initial load
duke
parents:
diff changeset
3681 _mapping_from(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3682 _mapping_from_opr(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3683 _mapping_to(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3684 _insert_list(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
3685 _insert_idx(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
3686 _insertion_buffer()
a61af66fc99e Initial load
duke
parents:
diff changeset
3687 {
a61af66fc99e Initial load
duke
parents:
diff changeset
3688 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3689 _register_blocked[i] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
3690 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3691 DEBUG_ONLY(check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3692 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3693
a61af66fc99e Initial load
duke
parents:
diff changeset
3694
a61af66fc99e Initial load
duke
parents:
diff changeset
3695 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3696
a61af66fc99e Initial load
duke
parents:
diff changeset
3697 void MoveResolver::check_empty() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3698 assert(_mapping_from.length() == 0 && _mapping_from_opr.length() == 0 && _mapping_to.length() == 0, "list must be empty before and after processing");
a61af66fc99e Initial load
duke
parents:
diff changeset
3699 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3700 assert(register_blocked(i) == 0, "register map must be empty before and after processing");
a61af66fc99e Initial load
duke
parents:
diff changeset
3701 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3702 assert(_multiple_reads_allowed == false, "must have default value");
a61af66fc99e Initial load
duke
parents:
diff changeset
3703 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3704
a61af66fc99e Initial load
duke
parents:
diff changeset
3705 void MoveResolver::verify_before_resolve() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3706 assert(_mapping_from.length() == _mapping_from_opr.length(), "length must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3707 assert(_mapping_from.length() == _mapping_to.length(), "length must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3708 assert(_insert_list != NULL && _insert_idx != -1, "insert position not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
3709
a61af66fc99e Initial load
duke
parents:
diff changeset
3710 int i, j;
a61af66fc99e Initial load
duke
parents:
diff changeset
3711 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3712 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3713 for (j = i + 1; j < _mapping_from.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3714 assert(_mapping_from.at(i) == NULL || _mapping_from.at(i) != _mapping_from.at(j), "cannot read from same interval twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3715 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3716 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3717 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3718
a61af66fc99e Initial load
duke
parents:
diff changeset
3719 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3720 for (j = i + 1; j < _mapping_to.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3721 assert(_mapping_to.at(i) != _mapping_to.at(j), "cannot write to same interval twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3722 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3723 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3724
a61af66fc99e Initial load
duke
parents:
diff changeset
3725
a61af66fc99e Initial load
duke
parents:
diff changeset
3726 BitMap used_regs(LinearScan::nof_regs + allocator()->frame_map()->argcount() + allocator()->max_spills());
a61af66fc99e Initial load
duke
parents:
diff changeset
3727 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3728 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3729 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3730 Interval* it = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3731 if (it != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3732 assert(!used_regs.at(it->assigned_reg()), "cannot read from same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3733 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3734
a61af66fc99e Initial load
duke
parents:
diff changeset
3735 if (it->assigned_regHi() != LinearScan::any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3736 assert(!used_regs.at(it->assigned_regHi()), "cannot read from same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3737 used_regs.set_bit(it->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
3738 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3739 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3740 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3741 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3742
a61af66fc99e Initial load
duke
parents:
diff changeset
3743 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3744 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3745 Interval* it = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3746 assert(!used_regs.at(it->assigned_reg()), "cannot write to same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3747 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3748
a61af66fc99e Initial load
duke
parents:
diff changeset
3749 if (it->assigned_regHi() != LinearScan::any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3750 assert(!used_regs.at(it->assigned_regHi()), "cannot write to same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3751 used_regs.set_bit(it->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
3752 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3753 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3754
a61af66fc99e Initial load
duke
parents:
diff changeset
3755 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3756 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3757 Interval* it = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3758 if (it != NULL && it->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3759 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3760 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3761 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3762 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3763 Interval* it = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3764 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");
a61af66fc99e Initial load
duke
parents:
diff changeset
3765 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3766 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3767
a61af66fc99e Initial load
duke
parents:
diff changeset
3768 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3769
a61af66fc99e Initial load
duke
parents:
diff changeset
3770
a61af66fc99e Initial load
duke
parents:
diff changeset
3771 // mark assigned_reg and assigned_regHi of the interval as blocked
a61af66fc99e Initial load
duke
parents:
diff changeset
3772 void MoveResolver::block_registers(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3773 int reg = it->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3774 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3775 assert(_multiple_reads_allowed || register_blocked(reg) == 0, "register already marked as used");
a61af66fc99e Initial load
duke
parents:
diff changeset
3776 set_register_blocked(reg, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3777 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3778 reg = it->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3779 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3780 assert(_multiple_reads_allowed || register_blocked(reg) == 0, "register already marked as used");
a61af66fc99e Initial load
duke
parents:
diff changeset
3781 set_register_blocked(reg, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3782 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3783 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3784
a61af66fc99e Initial load
duke
parents:
diff changeset
3785 // mark assigned_reg and assigned_regHi of the interval as unblocked
a61af66fc99e Initial load
duke
parents:
diff changeset
3786 void MoveResolver::unblock_registers(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3787 int reg = it->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3788 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3789 assert(register_blocked(reg) > 0, "register already marked as unused");
a61af66fc99e Initial load
duke
parents:
diff changeset
3790 set_register_blocked(reg, -1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3791 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3792 reg = it->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3793 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3794 assert(register_blocked(reg) > 0, "register already marked as unused");
a61af66fc99e Initial load
duke
parents:
diff changeset
3795 set_register_blocked(reg, -1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3796 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3797 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3798
a61af66fc99e Initial load
duke
parents:
diff changeset
3799 // check if assigned_reg and assigned_regHi of the to-interval are not blocked (or only blocked by from)
a61af66fc99e Initial load
duke
parents:
diff changeset
3800 bool MoveResolver::save_to_process_move(Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3801 int from_reg = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3802 int from_regHi = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3803 if (from != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3804 from_reg = from->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3805 from_regHi = from->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3806 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3807
a61af66fc99e Initial load
duke
parents:
diff changeset
3808 int reg = to->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3809 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3810 if (register_blocked(reg) > 1 || (register_blocked(reg) == 1 && reg != from_reg && reg != from_regHi)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3811 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3812 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3813 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3814 reg = to->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3815 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3816 if (register_blocked(reg) > 1 || (register_blocked(reg) == 1 && reg != from_reg && reg != from_regHi)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3817 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3818 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3819 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3820
a61af66fc99e Initial load
duke
parents:
diff changeset
3821 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3822 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3823
a61af66fc99e Initial load
duke
parents:
diff changeset
3824
a61af66fc99e Initial load
duke
parents:
diff changeset
3825 void MoveResolver::create_insertion_buffer(LIR_List* list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3826 assert(!_insertion_buffer.initialized(), "overwriting existing buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3827 _insertion_buffer.init(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3828 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3829
a61af66fc99e Initial load
duke
parents:
diff changeset
3830 void MoveResolver::append_insertion_buffer() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3831 if (_insertion_buffer.initialized()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3832 _insertion_buffer.lir_list()->append(&_insertion_buffer);
a61af66fc99e Initial load
duke
parents:
diff changeset
3833 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3834 assert(!_insertion_buffer.initialized(), "must be uninitialized now");
a61af66fc99e Initial load
duke
parents:
diff changeset
3835
a61af66fc99e Initial load
duke
parents:
diff changeset
3836 _insert_list = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
3837 _insert_idx = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3838 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3839
a61af66fc99e Initial load
duke
parents:
diff changeset
3840 void MoveResolver::insert_move(Interval* from_interval, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3841 assert(from_interval->reg_num() != to_interval->reg_num(), "from and to interval equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3842 assert(from_interval->type() == to_interval->type(), "move between different types");
a61af66fc99e Initial load
duke
parents:
diff changeset
3843 assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
a61af66fc99e Initial load
duke
parents:
diff changeset
3844 assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3845
a61af66fc99e Initial load
duke
parents:
diff changeset
3846 LIR_Opr from_opr = LIR_OprFact::virtual_register(from_interval->reg_num(), from_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3847 LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3848
a61af66fc99e Initial load
duke
parents:
diff changeset
3849 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3850 // the last_use flag is an optimization for FPU stack allocation. When the same
a61af66fc99e Initial load
duke
parents:
diff changeset
3851 // input interval is used in more than one move, then it is too difficult to determine
a61af66fc99e Initial load
duke
parents:
diff changeset
3852 // if this move is really the last use.
a61af66fc99e Initial load
duke
parents:
diff changeset
3853 from_opr = from_opr->make_last_use();
a61af66fc99e Initial load
duke
parents:
diff changeset
3854 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3855 _insertion_buffer.move(_insert_idx, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3856
a61af66fc99e Initial load
duke
parents:
diff changeset
3857 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3858 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3859
a61af66fc99e Initial load
duke
parents:
diff changeset
3860 void MoveResolver::insert_move(LIR_Opr from_opr, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3861 assert(from_opr->type() == to_interval->type(), "move between different types");
a61af66fc99e Initial load
duke
parents:
diff changeset
3862 assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
a61af66fc99e Initial load
duke
parents:
diff changeset
3863 assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3864
a61af66fc99e Initial load
duke
parents:
diff changeset
3865 LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3866 _insertion_buffer.move(_insert_idx, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3867
a61af66fc99e Initial load
duke
parents:
diff changeset
3868 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3869 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3870
a61af66fc99e Initial load
duke
parents:
diff changeset
3871
a61af66fc99e Initial load
duke
parents:
diff changeset
3872 void MoveResolver::resolve_mappings() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3873 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));
a61af66fc99e Initial load
duke
parents:
diff changeset
3874 DEBUG_ONLY(verify_before_resolve());
a61af66fc99e Initial load
duke
parents:
diff changeset
3875
a61af66fc99e Initial load
duke
parents:
diff changeset
3876 // Block all registers that are used as input operands of a move.
a61af66fc99e Initial load
duke
parents:
diff changeset
3877 // When a register is blocked, no move to this register is emitted.
a61af66fc99e Initial load
duke
parents:
diff changeset
3878 // This is necessary for detecting cycles in moves.
a61af66fc99e Initial load
duke
parents:
diff changeset
3879 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3880 for (i = _mapping_from.length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3881 Interval* from_interval = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3882 if (from_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3883 block_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3884 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3885 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3886
a61af66fc99e Initial load
duke
parents:
diff changeset
3887 int spill_candidate = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3888 while (_mapping_from.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3889 bool processed_interval = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3890
a61af66fc99e Initial load
duke
parents:
diff changeset
3891 for (i = _mapping_from.length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3892 Interval* from_interval = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3893 Interval* to_interval = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3894
a61af66fc99e Initial load
duke
parents:
diff changeset
3895 if (save_to_process_move(from_interval, to_interval)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3896 // this inverval can be processed because target is free
a61af66fc99e Initial load
duke
parents:
diff changeset
3897 if (from_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3898 insert_move(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3899 unblock_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3900 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3901 insert_move(_mapping_from_opr.at(i), to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3902 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3903 _mapping_from.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3904 _mapping_from_opr.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3905 _mapping_to.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3906
a61af66fc99e Initial load
duke
parents:
diff changeset
3907 processed_interval = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3908 } else if (from_interval != NULL && from_interval->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3909 // this interval cannot be processed now because target is not free
a61af66fc99e Initial load
duke
parents:
diff changeset
3910 // it starts in a register, so it is a possible candidate for spilling
a61af66fc99e Initial load
duke
parents:
diff changeset
3911 spill_candidate = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3912 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3913 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3914
a61af66fc99e Initial load
duke
parents:
diff changeset
3915 if (!processed_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3916 // no move could be processed because there is a cycle in the move list
a61af66fc99e Initial load
duke
parents:
diff changeset
3917 // (e.g. r1 -> r2, r2 -> r1), so one interval must be spilled to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
3918 assert(spill_candidate != -1, "no interval in register for spilling found");
a61af66fc99e Initial load
duke
parents:
diff changeset
3919
a61af66fc99e Initial load
duke
parents:
diff changeset
3920 // create a new spill interval and assign a stack slot to it
a61af66fc99e Initial load
duke
parents:
diff changeset
3921 Interval* from_interval = _mapping_from.at(spill_candidate);
a61af66fc99e Initial load
duke
parents:
diff changeset
3922 Interval* spill_interval = new Interval(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3923 spill_interval->set_type(from_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3924
a61af66fc99e Initial load
duke
parents:
diff changeset
3925 // add a dummy range because real position is difficult to calculate
a61af66fc99e Initial load
duke
parents:
diff changeset
3926 // Note: this range is a special case when the integrity of the allocation is checked
a61af66fc99e Initial load
duke
parents:
diff changeset
3927 spill_interval->add_range(1, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
3928
a61af66fc99e Initial load
duke
parents:
diff changeset
3929 // do not allocate a new spill slot for temporary interval, but
a61af66fc99e Initial load
duke
parents:
diff changeset
3930 // use spill slot assigned to from_interval. Otherwise moves from
a61af66fc99e Initial load
duke
parents:
diff changeset
3931 // one stack slot to another can happen (not allowed by LIR_Assembler
a61af66fc99e Initial load
duke
parents:
diff changeset
3932 int spill_slot = from_interval->canonical_spill_slot();
a61af66fc99e Initial load
duke
parents:
diff changeset
3933 if (spill_slot < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3934 spill_slot = allocator()->allocate_spill_slot(type2spill_size[spill_interval->type()] == 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
3935 from_interval->set_canonical_spill_slot(spill_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
3936 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3937 spill_interval->assign_reg(spill_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
3938 allocator()->append_interval(spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3939
a61af66fc99e Initial load
duke
parents:
diff changeset
3940 TRACE_LINEAR_SCAN(4, tty->print_cr("created new Interval %d for spilling", spill_interval->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3941
a61af66fc99e Initial load
duke
parents:
diff changeset
3942 // insert a move from register to stack and update the mapping
a61af66fc99e Initial load
duke
parents:
diff changeset
3943 insert_move(from_interval, spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3944 _mapping_from.at_put(spill_candidate, spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3945 unblock_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3946 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3947 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3948
a61af66fc99e Initial load
duke
parents:
diff changeset
3949 // reset to default value
a61af66fc99e Initial load
duke
parents:
diff changeset
3950 _multiple_reads_allowed = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3951
a61af66fc99e Initial load
duke
parents:
diff changeset
3952 // check that all intervals have been processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3953 DEBUG_ONLY(check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3954 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3955
a61af66fc99e Initial load
duke
parents:
diff changeset
3956
a61af66fc99e Initial load
duke
parents:
diff changeset
3957 void MoveResolver::set_insert_position(LIR_List* insert_list, int insert_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3958 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));
a61af66fc99e Initial load
duke
parents:
diff changeset
3959 assert(_insert_list == NULL && _insert_idx == -1, "use move_insert_position instead of set_insert_position when data already set");
a61af66fc99e Initial load
duke
parents:
diff changeset
3960
a61af66fc99e Initial load
duke
parents:
diff changeset
3961 create_insertion_buffer(insert_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3962 _insert_list = insert_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
3963 _insert_idx = insert_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
3964 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3965
a61af66fc99e Initial load
duke
parents:
diff changeset
3966 void MoveResolver::move_insert_position(LIR_List* insert_list, int insert_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3967 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));
a61af66fc99e Initial load
duke
parents:
diff changeset
3968
a61af66fc99e Initial load
duke
parents:
diff changeset
3969 if (_insert_list != NULL && (insert_list != _insert_list || insert_idx != _insert_idx)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3970 // insert position changed -> resolve current mappings
a61af66fc99e Initial load
duke
parents:
diff changeset
3971 resolve_mappings();
a61af66fc99e Initial load
duke
parents:
diff changeset
3972 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3973
a61af66fc99e Initial load
duke
parents:
diff changeset
3974 if (insert_list != _insert_list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3975 // block changed -> append insertion_buffer because it is
a61af66fc99e Initial load
duke
parents:
diff changeset
3976 // bound to a specific block and create a new insertion_buffer
a61af66fc99e Initial load
duke
parents:
diff changeset
3977 append_insertion_buffer();
a61af66fc99e Initial load
duke
parents:
diff changeset
3978 create_insertion_buffer(insert_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3979 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3980
a61af66fc99e Initial load
duke
parents:
diff changeset
3981 _insert_list = insert_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
3982 _insert_idx = insert_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
3983 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3984
a61af66fc99e Initial load
duke
parents:
diff changeset
3985 void MoveResolver::add_mapping(Interval* from_interval, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3986 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3987
a61af66fc99e Initial load
duke
parents:
diff changeset
3988 _mapping_from.append(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3989 _mapping_from_opr.append(LIR_OprFact::illegalOpr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3990 _mapping_to.append(to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3991 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3992
a61af66fc99e Initial load
duke
parents:
diff changeset
3993
a61af66fc99e Initial load
duke
parents:
diff changeset
3994 void MoveResolver::add_mapping(LIR_Opr from_opr, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3995 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3996 assert(from_opr->is_constant(), "only for constants");
a61af66fc99e Initial load
duke
parents:
diff changeset
3997
a61af66fc99e Initial load
duke
parents:
diff changeset
3998 _mapping_from.append(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3999 _mapping_from_opr.append(from_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
4000 _mapping_to.append(to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
4001 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4002
a61af66fc99e Initial load
duke
parents:
diff changeset
4003 void MoveResolver::resolve_and_append_moves() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4004 if (has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4005 resolve_mappings();
a61af66fc99e Initial load
duke
parents:
diff changeset
4006 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4007 append_insertion_buffer();
a61af66fc99e Initial load
duke
parents:
diff changeset
4008 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4009
a61af66fc99e Initial load
duke
parents:
diff changeset
4010
a61af66fc99e Initial load
duke
parents:
diff changeset
4011
a61af66fc99e Initial load
duke
parents:
diff changeset
4012 // **** Implementation of Range *************************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4013
a61af66fc99e Initial load
duke
parents:
diff changeset
4014 Range::Range(int from, int to, Range* next) :
a61af66fc99e Initial load
duke
parents:
diff changeset
4015 _from(from),
a61af66fc99e Initial load
duke
parents:
diff changeset
4016 _to(to),
a61af66fc99e Initial load
duke
parents:
diff changeset
4017 _next(next)
a61af66fc99e Initial load
duke
parents:
diff changeset
4018 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4019 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4020
a61af66fc99e Initial load
duke
parents:
diff changeset
4021 // initialize sentinel
a61af66fc99e Initial load
duke
parents:
diff changeset
4022 Range* Range::_end = NULL;
1584
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4023 void Range::initialize(Arena* arena) {
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4024 _end = new (arena) Range(max_jint, max_jint, NULL);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4025 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4026
a61af66fc99e Initial load
duke
parents:
diff changeset
4027 int Range::intersects_at(Range* r2) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4028 const Range* r1 = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4029
a61af66fc99e Initial load
duke
parents:
diff changeset
4030 assert(r1 != NULL && r2 != NULL, "null ranges not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
4031 assert(r1 != _end && r2 != _end, "empty ranges not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
4032
a61af66fc99e Initial load
duke
parents:
diff changeset
4033 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
4034 if (r1->from() < r2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4035 if (r1->to() <= r2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4036 r1 = r1->next(); if (r1 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4037 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4038 return r2->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
4039 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4040 } else if (r2->from() < r1->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4041 if (r2->to() <= r1->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4042 r2 = r2->next(); if (r2 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4043 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4044 return r1->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
4045 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4046 } else { // r1->from() == r2->from()
a61af66fc99e Initial load
duke
parents:
diff changeset
4047 if (r1->from() == r1->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4048 r1 = r1->next(); if (r1 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4049 } else if (r2->from() == r2->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4050 r2 = r2->next(); if (r2 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4051 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4052 return r1->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
4053 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4054 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4055 } while (true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4056 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4057
a61af66fc99e Initial load
duke
parents:
diff changeset
4058 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4059 void Range::print(outputStream* out) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4060 out->print("[%d, %d[ ", _from, _to);
a61af66fc99e Initial load
duke
parents:
diff changeset
4061 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4062 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4063
a61af66fc99e Initial load
duke
parents:
diff changeset
4064
a61af66fc99e Initial load
duke
parents:
diff changeset
4065
a61af66fc99e Initial load
duke
parents:
diff changeset
4066 // **** Implementation of Interval **********************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4067
a61af66fc99e Initial load
duke
parents:
diff changeset
4068 // initialize sentinel
a61af66fc99e Initial load
duke
parents:
diff changeset
4069 Interval* Interval::_end = NULL;
1584
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4070 void Interval::initialize(Arena* arena) {
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4071 Range::initialize(arena);
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4072 _end = new (arena) Interval(-1);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4073 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4074
a61af66fc99e Initial load
duke
parents:
diff changeset
4075 Interval::Interval(int reg_num) :
a61af66fc99e Initial load
duke
parents:
diff changeset
4076 _reg_num(reg_num),
a61af66fc99e Initial load
duke
parents:
diff changeset
4077 _type(T_ILLEGAL),
a61af66fc99e Initial load
duke
parents:
diff changeset
4078 _first(Range::end()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4079 _use_pos_and_kinds(12),
a61af66fc99e Initial load
duke
parents:
diff changeset
4080 _current(Range::end()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4081 _next(_end),
a61af66fc99e Initial load
duke
parents:
diff changeset
4082 _state(invalidState),
a61af66fc99e Initial load
duke
parents:
diff changeset
4083 _assigned_reg(LinearScan::any_reg),
a61af66fc99e Initial load
duke
parents:
diff changeset
4084 _assigned_regHi(LinearScan::any_reg),
a61af66fc99e Initial load
duke
parents:
diff changeset
4085 _cached_to(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
4086 _cached_opr(LIR_OprFact::illegalOpr),
a61af66fc99e Initial load
duke
parents:
diff changeset
4087 _cached_vm_reg(VMRegImpl::Bad()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4088 _split_children(0),
a61af66fc99e Initial load
duke
parents:
diff changeset
4089 _canonical_spill_slot(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
4090 _insert_move_when_activated(false),
a61af66fc99e Initial load
duke
parents:
diff changeset
4091 _register_hint(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
4092 _spill_state(noDefinitionFound),
a61af66fc99e Initial load
duke
parents:
diff changeset
4093 _spill_definition_pos(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
4094 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4095 _split_parent = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4096 _current_split_child = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4097 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4098
a61af66fc99e Initial load
duke
parents:
diff changeset
4099 int Interval::calc_to() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4100 assert(_first != Range::end(), "interval has no range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4101
a61af66fc99e Initial load
duke
parents:
diff changeset
4102 Range* r = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4103 while (r->next() != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4104 r = r->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4105 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4106 return r->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4107 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4108
a61af66fc99e Initial load
duke
parents:
diff changeset
4109
a61af66fc99e Initial load
duke
parents:
diff changeset
4110 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4111 // consistency check of split-children
a61af66fc99e Initial load
duke
parents:
diff changeset
4112 void Interval::check_split_children() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4113 if (_split_children.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4114 assert(is_split_parent(), "only split parents can have children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4115
a61af66fc99e Initial load
duke
parents:
diff changeset
4116 for (int i = 0; i < _split_children.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4117 Interval* i1 = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4118
a61af66fc99e Initial load
duke
parents:
diff changeset
4119 assert(i1->split_parent() == this, "not a split child of this interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4120 assert(i1->type() == type(), "must be equal for all split children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4121 assert(i1->canonical_spill_slot() == canonical_spill_slot(), "must be equal for all split children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4122
a61af66fc99e Initial load
duke
parents:
diff changeset
4123 for (int j = i + 1; j < _split_children.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4124 Interval* i2 = _split_children.at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
4125
a61af66fc99e Initial load
duke
parents:
diff changeset
4126 assert(i1->reg_num() != i2->reg_num(), "same register number");
a61af66fc99e Initial load
duke
parents:
diff changeset
4127
a61af66fc99e Initial load
duke
parents:
diff changeset
4128 if (i1->from() < i2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4129 assert(i1->to() <= i2->from() && i1->to() < i2->to(), "intervals overlapping");
a61af66fc99e Initial load
duke
parents:
diff changeset
4130 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4131 assert(i2->from() < i1->from(), "intervals start at same op_id");
a61af66fc99e Initial load
duke
parents:
diff changeset
4132 assert(i2->to() <= i1->from() && i2->to() < i1->to(), "intervals overlapping");
a61af66fc99e Initial load
duke
parents:
diff changeset
4133 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4134 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4135 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4137 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4138 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4139
a61af66fc99e Initial load
duke
parents:
diff changeset
4140 Interval* Interval::register_hint(bool search_split_child) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4141 if (!search_split_child) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4142 return _register_hint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4143 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4144
a61af66fc99e Initial load
duke
parents:
diff changeset
4145 if (_register_hint != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4146 assert(_register_hint->is_split_parent(), "ony split parents are valid hint registers");
a61af66fc99e Initial load
duke
parents:
diff changeset
4147
a61af66fc99e Initial load
duke
parents:
diff changeset
4148 if (_register_hint->assigned_reg() >= 0 && _register_hint->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4149 return _register_hint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4150
a61af66fc99e Initial load
duke
parents:
diff changeset
4151 } else if (_register_hint->_split_children.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4152 // search the first split child that has a register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
4153 int len = _register_hint->_split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4154 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4155 Interval* cur = _register_hint->_split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4156
a61af66fc99e Initial load
duke
parents:
diff changeset
4157 if (cur->assigned_reg() >= 0 && cur->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4158 return cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4159 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4160 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4162 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4163
a61af66fc99e Initial load
duke
parents:
diff changeset
4164 // no hint interval found that has a register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
4165 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4166 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4167
a61af66fc99e Initial load
duke
parents:
diff changeset
4168
a61af66fc99e Initial load
duke
parents:
diff changeset
4169 Interval* Interval::split_child_at_op_id(int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4170 assert(is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
4171 assert(op_id >= 0, "invalid op_id (method can not be called for spill moves)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4172
a61af66fc99e Initial load
duke
parents:
diff changeset
4173 Interval* result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4174 if (_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4175 result = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4176 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4177 result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4178 int len = _split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4179
a61af66fc99e Initial load
duke
parents:
diff changeset
4180 // in outputMode, the end of the interval (op_id == cur->to()) is not valid
a61af66fc99e Initial load
duke
parents:
diff changeset
4181 int to_offset = (mode == LIR_OpVisitState::outputMode ? 0 : 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4182
a61af66fc99e Initial load
duke
parents:
diff changeset
4183 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
4184 for (i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4185 Interval* cur = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4186 if (cur->from() <= op_id && op_id < cur->to() + to_offset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4187 if (i > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4188 // exchange current split child to start of list (faster access for next call)
a61af66fc99e Initial load
duke
parents:
diff changeset
4189 _split_children.at_put(i, _split_children.at(0));
a61af66fc99e Initial load
duke
parents:
diff changeset
4190 _split_children.at_put(0, cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4191 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4192
a61af66fc99e Initial load
duke
parents:
diff changeset
4193 // interval found
a61af66fc99e Initial load
duke
parents:
diff changeset
4194 result = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4195 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
4196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4197 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4198
a61af66fc99e Initial load
duke
parents:
diff changeset
4199 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4200 for (i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4201 Interval* tmp = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4202 if (tmp != result && tmp->from() <= op_id && op_id < tmp->to() + to_offset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4203 tty->print_cr("two valid result intervals found for op_id %d: %d and %d", op_id, result->reg_num(), tmp->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
4204 result->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4205 tmp->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4206 assert(false, "two valid result intervals found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4207 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4208 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4209 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4210 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4211
a61af66fc99e Initial load
duke
parents:
diff changeset
4212 assert(result != NULL, "no matching interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4213 assert(result->covers(op_id, mode), "op_id not covered by interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4214
a61af66fc99e Initial load
duke
parents:
diff changeset
4215 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4217
a61af66fc99e Initial load
duke
parents:
diff changeset
4218
a61af66fc99e Initial load
duke
parents:
diff changeset
4219 // returns the last split child that ends before the given op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
4220 Interval* Interval::split_child_before_op_id(int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4221 assert(op_id >= 0, "invalid op_id");
a61af66fc99e Initial load
duke
parents:
diff changeset
4222
a61af66fc99e Initial load
duke
parents:
diff changeset
4223 Interval* parent = split_parent();
a61af66fc99e Initial load
duke
parents:
diff changeset
4224 Interval* result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4225
a61af66fc99e Initial load
duke
parents:
diff changeset
4226 int len = parent->_split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4227 assert(len > 0, "no split children available");
a61af66fc99e Initial load
duke
parents:
diff changeset
4228
a61af66fc99e Initial load
duke
parents:
diff changeset
4229 for (int i = len - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4230 Interval* cur = parent->_split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4231 if (cur->to() <= op_id && (result == NULL || result->to() < cur->to())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4232 result = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4233 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4234 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4235
a61af66fc99e Initial load
duke
parents:
diff changeset
4236 assert(result != NULL, "no split child found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4237 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4238 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4239
a61af66fc99e Initial load
duke
parents:
diff changeset
4240
a61af66fc99e Initial load
duke
parents:
diff changeset
4241 // checks if op_id is covered by any split child
a61af66fc99e Initial load
duke
parents:
diff changeset
4242 bool Interval::split_child_covers(int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4243 assert(is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
4244 assert(op_id >= 0, "invalid op_id (method can not be called for spill moves)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4245
a61af66fc99e Initial load
duke
parents:
diff changeset
4246 if (_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4247 // simple case if interval was not split
a61af66fc99e Initial load
duke
parents:
diff changeset
4248 return covers(op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
4249
a61af66fc99e Initial load
duke
parents:
diff changeset
4250 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4251 // extended case: check all split children
a61af66fc99e Initial load
duke
parents:
diff changeset
4252 int len = _split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4253 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4254 Interval* cur = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4255 if (cur->covers(op_id, mode)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4256 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4258 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4259 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4260 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4261 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4262
a61af66fc99e Initial load
duke
parents:
diff changeset
4263
a61af66fc99e Initial load
duke
parents:
diff changeset
4264 // Note: use positions are sorted descending -> first use has highest index
a61af66fc99e Initial load
duke
parents:
diff changeset
4265 int Interval::first_usage(IntervalUseKind min_use_kind) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4266 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4267
a61af66fc99e Initial load
duke
parents:
diff changeset
4268 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4269 if (_use_pos_and_kinds.at(i + 1) >= min_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4270 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4271 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4272 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4273 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4274 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4275
a61af66fc99e Initial load
duke
parents:
diff changeset
4276 int Interval::next_usage(IntervalUseKind min_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4277 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4278
a61af66fc99e Initial load
duke
parents:
diff changeset
4279 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4280 if (_use_pos_and_kinds.at(i) >= from && _use_pos_and_kinds.at(i + 1) >= min_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4281 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4282 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4283 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4284 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4285 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4286
a61af66fc99e Initial load
duke
parents:
diff changeset
4287 int Interval::next_usage_exact(IntervalUseKind exact_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4288 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4289
a61af66fc99e Initial load
duke
parents:
diff changeset
4290 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4291 if (_use_pos_and_kinds.at(i) >= from && _use_pos_and_kinds.at(i + 1) == exact_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4292 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4293 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4294 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4295 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4296 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4297
a61af66fc99e Initial load
duke
parents:
diff changeset
4298 int Interval::previous_usage(IntervalUseKind min_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4299 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4300
a61af66fc99e Initial load
duke
parents:
diff changeset
4301 int prev = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4302 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4303 if (_use_pos_and_kinds.at(i) > from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4304 return prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4305 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4306 if (_use_pos_and_kinds.at(i + 1) >= min_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4307 prev = _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4308 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4309 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4310 return prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4311 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4312
a61af66fc99e Initial load
duke
parents:
diff changeset
4313 void Interval::add_use_pos(int pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4314 assert(covers(pos, LIR_OpVisitState::inputMode), "use position not covered by live range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4315
a61af66fc99e Initial load
duke
parents:
diff changeset
4316 // do not add use positions for precolored intervals because
a61af66fc99e Initial load
duke
parents:
diff changeset
4317 // they are never used
a61af66fc99e Initial load
duke
parents:
diff changeset
4318 if (use_kind != noUse && reg_num() >= LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4319 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4320 assert(_use_pos_and_kinds.length() % 2 == 0, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4321 for (int i = 0; i < _use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4322 assert(pos <= _use_pos_and_kinds.at(i), "already added a use-position with lower position");
a61af66fc99e Initial load
duke
parents:
diff changeset
4323 assert(_use_pos_and_kinds.at(i + 1) >= firstValidKind && _use_pos_and_kinds.at(i + 1) <= lastValidKind, "invalid use kind");
a61af66fc99e Initial load
duke
parents:
diff changeset
4324 if (i > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4325 assert(_use_pos_and_kinds.at(i) < _use_pos_and_kinds.at(i - 2), "not sorted descending");
a61af66fc99e Initial load
duke
parents:
diff changeset
4326 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4327 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4328 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4329
a61af66fc99e Initial load
duke
parents:
diff changeset
4330 // Note: add_use is called in descending order, so list gets sorted
a61af66fc99e Initial load
duke
parents:
diff changeset
4331 // automatically by just appending new use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4332 int len = _use_pos_and_kinds.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4333 if (len == 0 || _use_pos_and_kinds.at(len - 2) > pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4334 _use_pos_and_kinds.append(pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4335 _use_pos_and_kinds.append(use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4336 } else if (_use_pos_and_kinds.at(len - 1) < use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4337 assert(_use_pos_and_kinds.at(len - 2) == pos, "list not sorted correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
4338 _use_pos_and_kinds.at_put(len - 1, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4339 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4340 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4341 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4342
a61af66fc99e Initial load
duke
parents:
diff changeset
4343 void Interval::add_range(int from, int to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4344 assert(from < to, "invalid range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4345 assert(first() == Range::end() || to < first()->next()->from(), "not inserting at begin of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4346 assert(from <= first()->to(), "not inserting at begin of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4347
a61af66fc99e Initial load
duke
parents:
diff changeset
4348 if (first()->from() <= to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4349 // join intersecting ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4350 first()->set_from(MIN2(from, first()->from()));
a61af66fc99e Initial load
duke
parents:
diff changeset
4351 first()->set_to (MAX2(to, first()->to()));
a61af66fc99e Initial load
duke
parents:
diff changeset
4352 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4353 // insert new range
a61af66fc99e Initial load
duke
parents:
diff changeset
4354 _first = new Range(from, to, first());
a61af66fc99e Initial load
duke
parents:
diff changeset
4355 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4356 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4357
a61af66fc99e Initial load
duke
parents:
diff changeset
4358 Interval* Interval::new_split_child() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4359 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4360 Interval* result = new Interval(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4361 result->set_type(type());
a61af66fc99e Initial load
duke
parents:
diff changeset
4362
a61af66fc99e Initial load
duke
parents:
diff changeset
4363 Interval* parent = split_parent();
a61af66fc99e Initial load
duke
parents:
diff changeset
4364 result->_split_parent = parent;
a61af66fc99e Initial load
duke
parents:
diff changeset
4365 result->set_register_hint(parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
4366
a61af66fc99e Initial load
duke
parents:
diff changeset
4367 // insert new interval in children-list of parent
a61af66fc99e Initial load
duke
parents:
diff changeset
4368 if (parent->_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4369 assert(is_split_parent(), "list must be initialized at first split");
a61af66fc99e Initial load
duke
parents:
diff changeset
4370
a61af66fc99e Initial load
duke
parents:
diff changeset
4371 parent->_split_children = IntervalList(4);
a61af66fc99e Initial load
duke
parents:
diff changeset
4372 parent->_split_children.append(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
4373 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4374 parent->_split_children.append(result);
a61af66fc99e Initial load
duke
parents:
diff changeset
4375
a61af66fc99e Initial load
duke
parents:
diff changeset
4376 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4377 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4378
a61af66fc99e Initial load
duke
parents:
diff changeset
4379 // split this interval at the specified position and return
a61af66fc99e Initial load
duke
parents:
diff changeset
4380 // the remainder as a new interval.
a61af66fc99e Initial load
duke
parents:
diff changeset
4381 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4382 // when an interval is split, a bi-directional link is established between the original interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4383 // (the split parent) and the intervals that are split off this interval (the split children)
a61af66fc99e Initial load
duke
parents:
diff changeset
4384 // When a split child is split again, the new created interval is also a direct child
a61af66fc99e Initial load
duke
parents:
diff changeset
4385 // of the original parent (there is no tree of split children stored, but a flat list)
a61af66fc99e Initial load
duke
parents:
diff changeset
4386 // All split children are spilled to the same stack slot (stored in _canonical_spill_slot)
a61af66fc99e Initial load
duke
parents:
diff changeset
4387 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4388 // Note: The new interval has no valid reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
4389 Interval* Interval::split(int split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4390 assert(LinearScan::is_virtual_interval(this), "cannot split fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4391
a61af66fc99e Initial load
duke
parents:
diff changeset
4392 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4393 Interval* result = new_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
4394
a61af66fc99e Initial load
duke
parents:
diff changeset
4395 // split the ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4396 Range* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4397 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4398 while (cur != Range::end() && cur->to() <= split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4399 prev = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4400 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4401 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4402 assert(cur != Range::end(), "split interval after end of last range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4403
a61af66fc99e Initial load
duke
parents:
diff changeset
4404 if (cur->from() < split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4405 result->_first = new Range(split_pos, cur->to(), cur->next());
a61af66fc99e Initial load
duke
parents:
diff changeset
4406 cur->set_to(split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4407 cur->set_next(Range::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4408
a61af66fc99e Initial load
duke
parents:
diff changeset
4409 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4410 assert(prev != NULL, "split before start of first range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4411 result->_first = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4412 prev->set_next(Range::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4413 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4414 result->_current = result->_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4415 _cached_to = -1; // clear cached value
a61af66fc99e Initial load
duke
parents:
diff changeset
4416
a61af66fc99e Initial load
duke
parents:
diff changeset
4417 // split list of use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4418 int total_len = _use_pos_and_kinds.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4419 int start_idx = total_len - 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4420 while (start_idx >= 0 && _use_pos_and_kinds.at(start_idx) < split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4421 start_idx -= 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4422 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4423
a61af66fc99e Initial load
duke
parents:
diff changeset
4424 intStack new_use_pos_and_kinds(total_len - start_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
4425 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
4426 for (i = start_idx + 2; i < total_len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4427 new_use_pos_and_kinds.append(_use_pos_and_kinds.at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
4428 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4429
a61af66fc99e Initial load
duke
parents:
diff changeset
4430 _use_pos_and_kinds.truncate(start_idx + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
4431 result->_use_pos_and_kinds = _use_pos_and_kinds;
a61af66fc99e Initial load
duke
parents:
diff changeset
4432 _use_pos_and_kinds = new_use_pos_and_kinds;
a61af66fc99e Initial load
duke
parents:
diff changeset
4433
a61af66fc99e Initial load
duke
parents:
diff changeset
4434 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4435 assert(_use_pos_and_kinds.length() % 2 == 0, "must have use kind for each use pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
4436 assert(result->_use_pos_and_kinds.length() % 2 == 0, "must have use kind for each use pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
4437 assert(_use_pos_and_kinds.length() + result->_use_pos_and_kinds.length() == total_len, "missed some entries");
a61af66fc99e Initial load
duke
parents:
diff changeset
4438
a61af66fc99e Initial load
duke
parents:
diff changeset
4439 for (i = 0; i < _use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4440 assert(_use_pos_and_kinds.at(i) < split_pos, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4441 assert(_use_pos_and_kinds.at(i + 1) >= firstValidKind && _use_pos_and_kinds.at(i + 1) <= lastValidKind, "invalid use kind");
a61af66fc99e Initial load
duke
parents:
diff changeset
4442 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4443 for (i = 0; i < result->_use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4444 assert(result->_use_pos_and_kinds.at(i) >= split_pos, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4445 assert(result->_use_pos_and_kinds.at(i + 1) >= firstValidKind && result->_use_pos_and_kinds.at(i + 1) <= lastValidKind, "invalid use kind");
a61af66fc99e Initial load
duke
parents:
diff changeset
4446 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4447 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4448
a61af66fc99e Initial load
duke
parents:
diff changeset
4449 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4450 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4451
a61af66fc99e Initial load
duke
parents:
diff changeset
4452 // split this interval at the specified position and return
a61af66fc99e Initial load
duke
parents:
diff changeset
4453 // the head as a new interval (the original interval is the tail)
a61af66fc99e Initial load
duke
parents:
diff changeset
4454 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4455 // Currently, only the first range can be split, and the new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4456 // must not have split positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4457 Interval* Interval::split_from_start(int split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4458 assert(LinearScan::is_virtual_interval(this), "cannot split fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4459 assert(split_pos > from() && split_pos < to(), "can only split inside interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4460 assert(split_pos > _first->from() && split_pos <= _first->to(), "can only split inside first range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4461 assert(first_usage(noUse) > split_pos, "can not split when use positions are present");
a61af66fc99e Initial load
duke
parents:
diff changeset
4462
a61af66fc99e Initial load
duke
parents:
diff changeset
4463 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4464 Interval* result = new_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
4465
a61af66fc99e Initial load
duke
parents:
diff changeset
4466 // the new created interval has only one range (checked by assertion above),
a61af66fc99e Initial load
duke
parents:
diff changeset
4467 // so the splitting of the ranges is very simple
a61af66fc99e Initial load
duke
parents:
diff changeset
4468 result->add_range(_first->from(), split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4469
a61af66fc99e Initial load
duke
parents:
diff changeset
4470 if (split_pos == _first->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4471 assert(_first->next() != Range::end(), "must not be at end");
a61af66fc99e Initial load
duke
parents:
diff changeset
4472 _first = _first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4473 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4474 _first->set_from(split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4475 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4476
a61af66fc99e Initial load
duke
parents:
diff changeset
4477 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4478 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4479
a61af66fc99e Initial load
duke
parents:
diff changeset
4480
a61af66fc99e Initial load
duke
parents:
diff changeset
4481 // returns true if the op_id is inside the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4482 bool Interval::covers(int op_id, LIR_OpVisitState::OprMode mode) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4483 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4484
a61af66fc99e Initial load
duke
parents:
diff changeset
4485 while (cur != Range::end() && cur->to() < op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4486 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4488 if (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4489 assert(cur->to() != cur->next()->from(), "ranges not separated");
a61af66fc99e Initial load
duke
parents:
diff changeset
4490
a61af66fc99e Initial load
duke
parents:
diff changeset
4491 if (mode == LIR_OpVisitState::outputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4492 return cur->from() <= op_id && op_id < cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4493 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4494 return cur->from() <= op_id && op_id <= cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4495 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4496 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4497 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4499
a61af66fc99e Initial load
duke
parents:
diff changeset
4500 // returns true if the interval has any hole between hole_from and hole_to
a61af66fc99e Initial load
duke
parents:
diff changeset
4501 // (even if the hole has only the length 1)
a61af66fc99e Initial load
duke
parents:
diff changeset
4502 bool Interval::has_hole_between(int hole_from, int hole_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4503 assert(hole_from < hole_to, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4504 assert(from() <= hole_from && hole_to <= to(), "index out of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4505
a61af66fc99e Initial load
duke
parents:
diff changeset
4506 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4507 while (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4508 assert(cur->to() < cur->next()->from(), "no space between ranges");
a61af66fc99e Initial load
duke
parents:
diff changeset
4509
a61af66fc99e Initial load
duke
parents:
diff changeset
4510 // hole-range starts before this range -> hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4511 if (hole_from < cur->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4512 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4513
a61af66fc99e Initial load
duke
parents:
diff changeset
4514 // hole-range completely inside this range -> no hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4515 } else if (hole_to <= cur->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4516 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4517
a61af66fc99e Initial load
duke
parents:
diff changeset
4518 // overlapping of hole-range with this range -> hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4519 } else if (hole_from <= cur->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4520 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4521 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4522
a61af66fc99e Initial load
duke
parents:
diff changeset
4523 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4524 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4525
a61af66fc99e Initial load
duke
parents:
diff changeset
4526 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4527 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4528
a61af66fc99e Initial load
duke
parents:
diff changeset
4529
a61af66fc99e Initial load
duke
parents:
diff changeset
4530 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4531 void Interval::print(outputStream* out) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4532 const char* SpillState2Name[] = { "no definition", "no spill store", "one spill store", "store at definition", "start in memory", "no optimization" };
a61af66fc99e Initial load
duke
parents:
diff changeset
4533 const char* UseKind2Name[] = { "N", "L", "S", "M" };
a61af66fc99e Initial load
duke
parents:
diff changeset
4534
a61af66fc99e Initial load
duke
parents:
diff changeset
4535 const char* type_name;
a61af66fc99e Initial load
duke
parents:
diff changeset
4536 LIR_Opr opr = LIR_OprFact::illegal();
a61af66fc99e Initial load
duke
parents:
diff changeset
4537 if (reg_num() < LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4538 type_name = "fixed";
a61af66fc99e Initial load
duke
parents:
diff changeset
4539 // need a temporary operand for fixed intervals because type() cannot be called
a61af66fc99e Initial load
duke
parents:
diff changeset
4540 if (assigned_reg() >= pd_first_cpu_reg && assigned_reg() <= pd_last_cpu_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4541 opr = LIR_OprFact::single_cpu(assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
4542 } else if (assigned_reg() >= pd_first_fpu_reg && assigned_reg() <= pd_last_fpu_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4543 opr = LIR_OprFact::single_fpu(assigned_reg() - pd_first_fpu_reg);
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
4544 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4545 } else if (assigned_reg() >= pd_first_xmm_reg && assigned_reg() <= pd_last_xmm_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4546 opr = LIR_OprFact::single_xmm(assigned_reg() - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
4547 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4548 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4549 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
4550 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4551 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4552 type_name = type2name(type());
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
4553 if (assigned_reg() != -1 &&
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
4554 (LinearScan::num_physical_regs(type()) == 1 || assigned_regHi() != -1)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4555 opr = LinearScan::calc_operand_for_interval(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
4556 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4557 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4558
a61af66fc99e Initial load
duke
parents:
diff changeset
4559 out->print("%d %s ", reg_num(), type_name);
a61af66fc99e Initial load
duke
parents:
diff changeset
4560 if (opr->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4561 out->print("\"");
a61af66fc99e Initial load
duke
parents:
diff changeset
4562 opr->print(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
4563 out->print("\" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
4564 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4565 out->print("%d %d ", split_parent()->reg_num(), (register_hint(false) != NULL ? register_hint(false)->reg_num() : -1));
a61af66fc99e Initial load
duke
parents:
diff changeset
4566
a61af66fc99e Initial load
duke
parents:
diff changeset
4567 // print ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4568 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4569 while (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4570 cur->print(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
4571 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4572 assert(cur != NULL, "range list not closed with range sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
4573 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4574
a61af66fc99e Initial load
duke
parents:
diff changeset
4575 // print use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4576 int prev = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4577 assert(_use_pos_and_kinds.length() % 2 == 0, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4578 for (int i =_use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4579 assert(_use_pos_and_kinds.at(i + 1) >= firstValidKind && _use_pos_and_kinds.at(i + 1) <= lastValidKind, "invalid use kind");
a61af66fc99e Initial load
duke
parents:
diff changeset
4580 assert(prev < _use_pos_and_kinds.at(i), "use positions not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
4581
a61af66fc99e Initial load
duke
parents:
diff changeset
4582 out->print("%d %s ", _use_pos_and_kinds.at(i), UseKind2Name[_use_pos_and_kinds.at(i + 1)]);
a61af66fc99e Initial load
duke
parents:
diff changeset
4583 prev = _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4584 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4585
a61af66fc99e Initial load
duke
parents:
diff changeset
4586 out->print(" \"%s\"", SpillState2Name[spill_state()]);
a61af66fc99e Initial load
duke
parents:
diff changeset
4587 out->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4588 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4589 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4590
a61af66fc99e Initial load
duke
parents:
diff changeset
4591
a61af66fc99e Initial load
duke
parents:
diff changeset
4592
a61af66fc99e Initial load
duke
parents:
diff changeset
4593 // **** Implementation of IntervalWalker ****************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4594
a61af66fc99e Initial load
duke
parents:
diff changeset
4595 IntervalWalker::IntervalWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4596 : _compilation(allocator->compilation())
a61af66fc99e Initial load
duke
parents:
diff changeset
4597 , _allocator(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
4598 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4599 _unhandled_first[fixedKind] = unhandled_fixed_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4600 _unhandled_first[anyKind] = unhandled_any_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4601 _active_first[fixedKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4602 _inactive_first[fixedKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4603 _active_first[anyKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4604 _inactive_first[anyKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4605 _current_position = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4606 _current = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4607 next_interval();
a61af66fc99e Initial load
duke
parents:
diff changeset
4608 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4609
a61af66fc99e Initial load
duke
parents:
diff changeset
4610
a61af66fc99e Initial load
duke
parents:
diff changeset
4611 // append interval at top of list
a61af66fc99e Initial load
duke
parents:
diff changeset
4612 void IntervalWalker::append_unsorted(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4613 interval->set_next(*list); *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4614 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4615
a61af66fc99e Initial load
duke
parents:
diff changeset
4616
a61af66fc99e Initial load
duke
parents:
diff changeset
4617 // append interval in order of current range from()
a61af66fc99e Initial load
duke
parents:
diff changeset
4618 void IntervalWalker::append_sorted(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4619 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4620 Interval* cur = *list;
a61af66fc99e Initial load
duke
parents:
diff changeset
4621 while (cur->current_from() < interval->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4622 prev = cur; cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4623 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4624 if (prev == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4625 *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4626 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4627 prev->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
4628 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4629 interval->set_next(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4630 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4631
a61af66fc99e Initial load
duke
parents:
diff changeset
4632 void IntervalWalker::append_to_unhandled(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4633 assert(interval->from() >= current()->current_from(), "cannot append new interval before current walk position");
a61af66fc99e Initial load
duke
parents:
diff changeset
4634
a61af66fc99e Initial load
duke
parents:
diff changeset
4635 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4636 Interval* cur = *list;
a61af66fc99e Initial load
duke
parents:
diff changeset
4637 while (cur->from() < interval->from() || (cur->from() == interval->from() && cur->first_usage(noUse) < interval->first_usage(noUse))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4638 prev = cur; cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4639 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4640 if (prev == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4641 *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4642 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4643 prev->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
4644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4645 interval->set_next(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4646 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4647
a61af66fc99e Initial load
duke
parents:
diff changeset
4648
a61af66fc99e Initial load
duke
parents:
diff changeset
4649 inline bool IntervalWalker::remove_from_list(Interval** list, Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4650 while (*list != Interval::end() && *list != i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4651 list = (*list)->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4652 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4653 if (*list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4654 assert(*list == i, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4655 *list = (*list)->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4656 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4657 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4658 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4659 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4660 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4661
a61af66fc99e Initial load
duke
parents:
diff changeset
4662 void IntervalWalker::remove_from_list(Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4663 bool deleted;
a61af66fc99e Initial load
duke
parents:
diff changeset
4664
a61af66fc99e Initial load
duke
parents:
diff changeset
4665 if (i->state() == activeState) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4666 deleted = remove_from_list(active_first_addr(anyKind), i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4667 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4668 assert(i->state() == inactiveState, "invalid state");
a61af66fc99e Initial load
duke
parents:
diff changeset
4669 deleted = remove_from_list(inactive_first_addr(anyKind), i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4670 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4671
a61af66fc99e Initial load
duke
parents:
diff changeset
4672 assert(deleted, "interval has not been found in list");
a61af66fc99e Initial load
duke
parents:
diff changeset
4673 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4674
a61af66fc99e Initial load
duke
parents:
diff changeset
4675
a61af66fc99e Initial load
duke
parents:
diff changeset
4676 void IntervalWalker::walk_to(IntervalState state, int from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4677 assert (state == activeState || state == inactiveState, "wrong state");
a61af66fc99e Initial load
duke
parents:
diff changeset
4678 for_each_interval_kind(kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4679 Interval** prev = state == activeState ? active_first_addr(kind) : inactive_first_addr(kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4680 Interval* next = *prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4681 while (next->current_from() <= from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4682 Interval* cur = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
4683 next = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4684
a61af66fc99e Initial load
duke
parents:
diff changeset
4685 bool range_has_changed = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4686 while (cur->current_to() <= from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4687 cur->next_range();
a61af66fc99e Initial load
duke
parents:
diff changeset
4688 range_has_changed = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4689 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4690
a61af66fc99e Initial load
duke
parents:
diff changeset
4691 // also handle move from inactive list to active list
a61af66fc99e Initial load
duke
parents:
diff changeset
4692 range_has_changed = range_has_changed || (state == inactiveState && cur->current_from() <= from);
a61af66fc99e Initial load
duke
parents:
diff changeset
4693
a61af66fc99e Initial load
duke
parents:
diff changeset
4694 if (range_has_changed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4695 // remove cur from list
a61af66fc99e Initial load
duke
parents:
diff changeset
4696 *prev = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
4697 if (cur->current_at_end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4698 // move to handled state (not maintained as a list)
a61af66fc99e Initial load
duke
parents:
diff changeset
4699 cur->set_state(handledState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4700 interval_moved(cur, kind, state, handledState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4701 } else if (cur->current_from() <= from){
a61af66fc99e Initial load
duke
parents:
diff changeset
4702 // sort into active list
a61af66fc99e Initial load
duke
parents:
diff changeset
4703 append_sorted(active_first_addr(kind), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4704 cur->set_state(activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4705 if (*prev == cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4706 assert(state == activeState, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4707 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4708 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4709 interval_moved(cur, kind, state, activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4710 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4711 // sort into inactive list
a61af66fc99e Initial load
duke
parents:
diff changeset
4712 append_sorted(inactive_first_addr(kind), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4713 cur->set_state(inactiveState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4714 if (*prev == cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4715 assert(state == inactiveState, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4716 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4717 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4718 interval_moved(cur, kind, state, inactiveState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4719 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4720 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4721 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4722 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
4723 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4724 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4725 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4726 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4727
a61af66fc99e Initial load
duke
parents:
diff changeset
4728
a61af66fc99e Initial load
duke
parents:
diff changeset
4729 void IntervalWalker::next_interval() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4730 IntervalKind kind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4731 Interval* any = _unhandled_first[anyKind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4732 Interval* fixed = _unhandled_first[fixedKind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4733
a61af66fc99e Initial load
duke
parents:
diff changeset
4734 if (any != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4735 // intervals may start at same position -> prefer fixed interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4736 kind = fixed != Interval::end() && fixed->from() <= any->from() ? fixedKind : anyKind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4737
a61af66fc99e Initial load
duke
parents:
diff changeset
4738 assert (kind == fixedKind && fixed->from() <= any->from() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
4739 kind == anyKind && any->from() <= fixed->from(), "wrong interval!!!");
a61af66fc99e Initial load
duke
parents:
diff changeset
4740 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");
a61af66fc99e Initial load
duke
parents:
diff changeset
4741
a61af66fc99e Initial load
duke
parents:
diff changeset
4742 } else if (fixed != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4743 kind = fixedKind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4744 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4745 _current = NULL; return;
a61af66fc99e Initial load
duke
parents:
diff changeset
4746 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4747 _current_kind = kind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4748 _current = _unhandled_first[kind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4749 _unhandled_first[kind] = _current->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4750 _current->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4751 _current->rewind_range();
a61af66fc99e Initial load
duke
parents:
diff changeset
4752 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4753
a61af66fc99e Initial load
duke
parents:
diff changeset
4754
a61af66fc99e Initial load
duke
parents:
diff changeset
4755 void IntervalWalker::walk_to(int lir_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4756 assert(_current_position <= lir_op_id, "can not walk backwards");
a61af66fc99e Initial load
duke
parents:
diff changeset
4757 while (current() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4758 bool is_active = current()->from() <= lir_op_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4759 int id = is_active ? current()->from() : lir_op_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4760
a61af66fc99e Initial load
duke
parents:
diff changeset
4761 TRACE_LINEAR_SCAN(2, if (_current_position < id) { tty->cr(); tty->print_cr("walk_to(%d) **************************************************************", id); })
a61af66fc99e Initial load
duke
parents:
diff changeset
4762
a61af66fc99e Initial load
duke
parents:
diff changeset
4763 // set _current_position prior to call of walk_to
a61af66fc99e Initial load
duke
parents:
diff changeset
4764 _current_position = id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4765
a61af66fc99e Initial load
duke
parents:
diff changeset
4766 // call walk_to even if _current_position == id
a61af66fc99e Initial load
duke
parents:
diff changeset
4767 walk_to(activeState, id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4768 walk_to(inactiveState, id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4769
a61af66fc99e Initial load
duke
parents:
diff changeset
4770 if (is_active) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4771 current()->set_state(activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4772 if (activate_current()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4773 append_sorted(active_first_addr(current_kind()), current());
a61af66fc99e Initial load
duke
parents:
diff changeset
4774 interval_moved(current(), current_kind(), unhandledState, activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4775 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4776
a61af66fc99e Initial load
duke
parents:
diff changeset
4777 next_interval();
a61af66fc99e Initial load
duke
parents:
diff changeset
4778 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4779 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
4780 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4781 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4782 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4783
a61af66fc99e Initial load
duke
parents:
diff changeset
4784 void IntervalWalker::interval_moved(Interval* interval, IntervalKind kind, IntervalState from, IntervalState to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4785 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4786 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4787 #define print_state(state) \
a61af66fc99e Initial load
duke
parents:
diff changeset
4788 switch(state) {\
a61af66fc99e Initial load
duke
parents:
diff changeset
4789 case unhandledState: tty->print("unhandled"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4790 case activeState: tty->print("active"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4791 case inactiveState: tty->print("inactive"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4792 case handledState: tty->print("handled"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4793 default: ShouldNotReachHere(); \
a61af66fc99e Initial load
duke
parents:
diff changeset
4794 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4795
a61af66fc99e Initial load
duke
parents:
diff changeset
4796 print_state(from); tty->print(" to "); print_state(to);
a61af66fc99e Initial load
duke
parents:
diff changeset
4797 tty->fill_to(23);
a61af66fc99e Initial load
duke
parents:
diff changeset
4798 interval->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4799
a61af66fc99e Initial load
duke
parents:
diff changeset
4800 #undef print_state
a61af66fc99e Initial load
duke
parents:
diff changeset
4801 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4802 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4803 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4804
a61af66fc99e Initial load
duke
parents:
diff changeset
4805
a61af66fc99e Initial load
duke
parents:
diff changeset
4806
a61af66fc99e Initial load
duke
parents:
diff changeset
4807 // **** Implementation of LinearScanWalker **************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4808
a61af66fc99e Initial load
duke
parents:
diff changeset
4809 LinearScanWalker::LinearScanWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4810 : IntervalWalker(allocator, unhandled_fixed_first, unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4811 , _move_resolver(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
4812 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4813 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4814 _spill_intervals[i] = new IntervalList(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
4815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4816 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4817
a61af66fc99e Initial load
duke
parents:
diff changeset
4818
a61af66fc99e Initial load
duke
parents:
diff changeset
4819 inline void LinearScanWalker::init_use_lists(bool only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4820 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4821 _use_pos[i] = max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4822
a61af66fc99e Initial load
duke
parents:
diff changeset
4823 if (!only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4824 _block_pos[i] = max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4825 _spill_intervals[i]->clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
4826 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4827 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4828 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4829
a61af66fc99e Initial load
duke
parents:
diff changeset
4830 inline void LinearScanWalker::exclude_from_use(int reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4831 assert(reg < LinearScan::nof_regs, "interval must have a register assigned (stack slots not allowed)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4832 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4833 _use_pos[reg] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4834 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4835 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4836 inline void LinearScanWalker::exclude_from_use(Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4837 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4838
a61af66fc99e Initial load
duke
parents:
diff changeset
4839 exclude_from_use(i->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
4840 exclude_from_use(i->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
4841 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4842
a61af66fc99e Initial load
duke
parents:
diff changeset
4843 inline void LinearScanWalker::set_use_pos(int reg, Interval* i, int use_pos, bool only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4844 assert(use_pos != 0, "must use exclude_from_use to set use_pos to 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
4845
a61af66fc99e Initial load
duke
parents:
diff changeset
4846 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4847 if (_use_pos[reg] > use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4848 _use_pos[reg] = use_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4849 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4850 if (!only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4851 _spill_intervals[reg]->append(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4852 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4853 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4854 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4855 inline void LinearScanWalker::set_use_pos(Interval* i, int use_pos, bool only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4856 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4857 if (use_pos != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4858 set_use_pos(i->assigned_reg(), i, use_pos, only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4859 set_use_pos(i->assigned_regHi(), i, use_pos, only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4860 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4861 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4862
a61af66fc99e Initial load
duke
parents:
diff changeset
4863 inline void LinearScanWalker::set_block_pos(int reg, Interval* i, int block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4864 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4865 if (_block_pos[reg] > block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4866 _block_pos[reg] = block_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4867 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4868 if (_use_pos[reg] > block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4869 _use_pos[reg] = block_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4870 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4871 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4872 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4873 inline void LinearScanWalker::set_block_pos(Interval* i, int block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4874 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4875 if (block_pos != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4876 set_block_pos(i->assigned_reg(), i, block_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4877 set_block_pos(i->assigned_regHi(), i, block_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4878 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4879 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4880
a61af66fc99e Initial load
duke
parents:
diff changeset
4881
a61af66fc99e Initial load
duke
parents:
diff changeset
4882 void LinearScanWalker::free_exclude_active_fixed() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4883 Interval* list = active_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4884 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4885 assert(list->assigned_reg() < LinearScan::nof_regs, "active interval must have a register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4886 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4887 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4888 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4889 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4890
a61af66fc99e Initial load
duke
parents:
diff changeset
4891 void LinearScanWalker::free_exclude_active_any() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4892 Interval* list = active_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4893 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4894 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4895 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4896 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4897 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4898
a61af66fc99e Initial load
duke
parents:
diff changeset
4899 void LinearScanWalker::free_collect_inactive_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4900 Interval* list = inactive_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4901 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4902 if (cur->to() <= list->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4903 assert(list->current_intersects_at(cur) == -1, "must not intersect");
a61af66fc99e Initial load
duke
parents:
diff changeset
4904 set_use_pos(list, list->current_from(), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4905 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4906 set_use_pos(list, list->current_intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4907 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4908 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4909 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4910 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4911
a61af66fc99e Initial load
duke
parents:
diff changeset
4912 void LinearScanWalker::free_collect_inactive_any(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4913 Interval* list = inactive_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4914 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4915 set_use_pos(list, list->current_intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4916 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4917 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4918 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4919
a61af66fc99e Initial load
duke
parents:
diff changeset
4920 void LinearScanWalker::free_collect_unhandled(IntervalKind kind, Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4921 Interval* list = unhandled_first(kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4922 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4923 set_use_pos(list, list->intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4924 if (kind == fixedKind && cur->to() <= list->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4925 set_use_pos(list, list->from(), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4926 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4927 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4928 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4929 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4930
a61af66fc99e Initial load
duke
parents:
diff changeset
4931 void LinearScanWalker::spill_exclude_active_fixed() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4932 Interval* list = active_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4933 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4934 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4935 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4936 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4937 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4938
a61af66fc99e Initial load
duke
parents:
diff changeset
4939 void LinearScanWalker::spill_block_unhandled_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4940 Interval* list = unhandled_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4941 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4942 set_block_pos(list, list->intersects_at(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
4943 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4944 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4945 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4946
a61af66fc99e Initial load
duke
parents:
diff changeset
4947 void LinearScanWalker::spill_block_inactive_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4948 Interval* list = inactive_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4949 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4950 if (cur->to() > list->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4951 set_block_pos(list, list->current_intersects_at(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
4952 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4953 assert(list->current_intersects_at(cur) == -1, "invalid optimization: intervals intersect");
a61af66fc99e Initial load
duke
parents:
diff changeset
4954 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4955
a61af66fc99e Initial load
duke
parents:
diff changeset
4956 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4957 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4958 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4959
a61af66fc99e Initial load
duke
parents:
diff changeset
4960 void LinearScanWalker::spill_collect_active_any() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4961 Interval* list = active_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4962 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4963 set_use_pos(list, MIN2(list->next_usage(loopEndMarker, _current_position), list->to()), false);
a61af66fc99e Initial load
duke
parents:
diff changeset
4964 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4965 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4966 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4967
a61af66fc99e Initial load
duke
parents:
diff changeset
4968 void LinearScanWalker::spill_collect_inactive_any(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4969 Interval* list = inactive_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4970 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4971 if (list->current_intersects(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4972 set_use_pos(list, MIN2(list->next_usage(loopEndMarker, _current_position), list->to()), false);
a61af66fc99e Initial load
duke
parents:
diff changeset
4973 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4974 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4975 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4976 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4977
a61af66fc99e Initial load
duke
parents:
diff changeset
4978
a61af66fc99e Initial load
duke
parents:
diff changeset
4979 void LinearScanWalker::insert_move(int op_id, Interval* src_it, Interval* dst_it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4980 // output all moves here. When source and target are equal, the move is
a61af66fc99e Initial load
duke
parents:
diff changeset
4981 // optimized away later in assign_reg_nums
a61af66fc99e Initial load
duke
parents:
diff changeset
4982
a61af66fc99e Initial load
duke
parents:
diff changeset
4983 op_id = (op_id + 1) & ~1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4984 BlockBegin* op_block = allocator()->block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4985 assert(op_id > 0 && allocator()->block_of_op_with_id(op_id - 2) == op_block, "cannot insert move at block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
4986
a61af66fc99e Initial load
duke
parents:
diff changeset
4987 // calculate index of instruction inside instruction list of current block
a61af66fc99e Initial load
duke
parents:
diff changeset
4988 // the minimal index (for a block with no spill moves) can be calculated because the
a61af66fc99e Initial load
duke
parents:
diff changeset
4989 // numbering of instructions is known.
a61af66fc99e Initial load
duke
parents:
diff changeset
4990 // When the block already contains spill moves, the index must be increased until the
a61af66fc99e Initial load
duke
parents:
diff changeset
4991 // correct index is reached.
a61af66fc99e Initial load
duke
parents:
diff changeset
4992 LIR_OpList* list = op_block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
4993 int index = (op_id - list->at(0)->id()) / 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4994 assert(list->at(index)->id() <= op_id, "error in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
4995
a61af66fc99e Initial load
duke
parents:
diff changeset
4996 while (list->at(index)->id() != op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4997 index++;
a61af66fc99e Initial load
duke
parents:
diff changeset
4998 assert(0 <= index && index < list->length(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
4999 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5000 assert(1 <= index && index < list->length(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
5001 assert(list->at(index)->id() == op_id, "error in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
5002
a61af66fc99e Initial load
duke
parents:
diff changeset
5003 // insert new instruction before instruction at position index
a61af66fc99e Initial load
duke
parents:
diff changeset
5004 _move_resolver.move_insert_position(op_block->lir(), index - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5005 _move_resolver.add_mapping(src_it, dst_it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5006 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5007
a61af66fc99e Initial load
duke
parents:
diff changeset
5008
a61af66fc99e Initial load
duke
parents:
diff changeset
5009 int LinearScanWalker::find_optimal_split_pos(BlockBegin* min_block, BlockBegin* max_block, int max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5010 int from_block_nr = min_block->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
5011 int to_block_nr = max_block->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
5012
a61af66fc99e Initial load
duke
parents:
diff changeset
5013 assert(0 <= from_block_nr && from_block_nr < block_count(), "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5014 assert(0 <= to_block_nr && to_block_nr < block_count(), "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5015 assert(from_block_nr < to_block_nr, "must cross block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
5016
a61af66fc99e Initial load
duke
parents:
diff changeset
5017 // Try to split at end of max_block. If this would be after
a61af66fc99e Initial load
duke
parents:
diff changeset
5018 // max_split_pos, then use the begin of max_block
a61af66fc99e Initial load
duke
parents:
diff changeset
5019 int optimal_split_pos = max_block->last_lir_instruction_id() + 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5020 if (optimal_split_pos > max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5021 optimal_split_pos = max_block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
5022 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5023
a61af66fc99e Initial load
duke
parents:
diff changeset
5024 int min_loop_depth = max_block->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
5025 for (int i = to_block_nr - 1; i >= from_block_nr; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5026 BlockBegin* cur = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5027
a61af66fc99e Initial load
duke
parents:
diff changeset
5028 if (cur->loop_depth() < min_loop_depth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5029 // block with lower loop-depth found -> split at the end of this block
a61af66fc99e Initial load
duke
parents:
diff changeset
5030 min_loop_depth = cur->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
5031 optimal_split_pos = cur->last_lir_instruction_id() + 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5032 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5033 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5034 assert(optimal_split_pos > allocator()->max_lir_op_id() || allocator()->is_block_begin(optimal_split_pos), "algorithm must move split pos to block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
5035
a61af66fc99e Initial load
duke
parents:
diff changeset
5036 return optimal_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5037 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5038
a61af66fc99e Initial load
duke
parents:
diff changeset
5039
a61af66fc99e Initial load
duke
parents:
diff changeset
5040 int LinearScanWalker::find_optimal_split_pos(Interval* it, int min_split_pos, int max_split_pos, bool do_loop_optimization) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5041 int optimal_split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5042 if (min_split_pos == max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5043 // trivial case, no optimization of split position possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5044 TRACE_LINEAR_SCAN(4, tty->print_cr(" min-pos and max-pos are equal, no optimization possible"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5045 optimal_split_pos = min_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5046
a61af66fc99e Initial load
duke
parents:
diff changeset
5047 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5048 assert(min_split_pos < max_split_pos, "must be true then");
a61af66fc99e Initial load
duke
parents:
diff changeset
5049 assert(min_split_pos > 0, "cannot access min_split_pos - 1 otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5050
a61af66fc99e Initial load
duke
parents:
diff changeset
5051 // reason for using min_split_pos - 1: when the minimal split pos is exactly at the
a61af66fc99e Initial load
duke
parents:
diff changeset
5052 // beginning of a block, then min_split_pos is also a possible split position.
a61af66fc99e Initial load
duke
parents:
diff changeset
5053 // Use the block before as min_block, because then min_block->last_lir_instruction_id() + 2 == min_split_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
5054 BlockBegin* min_block = allocator()->block_of_op_with_id(min_split_pos - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5055
a61af66fc99e Initial load
duke
parents:
diff changeset
5056 // reason for using max_split_pos - 1: otherwise there would be an assertion failure
a61af66fc99e Initial load
duke
parents:
diff changeset
5057 // when an interval ends at the end of the last block of the method
a61af66fc99e Initial load
duke
parents:
diff changeset
5058 // (in this case, max_split_pos == allocator()->max_lir_op_id() + 2, and there is no
a61af66fc99e Initial load
duke
parents:
diff changeset
5059 // block at this op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5060 BlockBegin* max_block = allocator()->block_of_op_with_id(max_split_pos - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5061
a61af66fc99e Initial load
duke
parents:
diff changeset
5062 assert(min_block->linear_scan_number() <= max_block->linear_scan_number(), "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5063 if (min_block == max_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5064 // split position cannot be moved to block boundary, so split as late as possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5065 TRACE_LINEAR_SCAN(4, tty->print_cr(" cannot move split pos to block boundary because min_pos and max_pos are in same block"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5066 optimal_split_pos = max_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5067
a61af66fc99e Initial load
duke
parents:
diff changeset
5068 } else if (it->has_hole_between(max_split_pos - 1, max_split_pos) && !allocator()->is_block_begin(max_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5069 // Do not move split position if the interval has a hole before max_split_pos.
a61af66fc99e Initial load
duke
parents:
diff changeset
5070 // Intervals resulting from Phi-Functions have more than one definition (marked
a61af66fc99e Initial load
duke
parents:
diff changeset
5071 // as mustHaveRegister) with a hole before each definition. When the register is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5072 // for the second definition, an earlier reloading is unnecessary.
a61af66fc99e Initial load
duke
parents:
diff changeset
5073 TRACE_LINEAR_SCAN(4, tty->print_cr(" interval has hole just before max_split_pos, so splitting at max_split_pos"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5074 optimal_split_pos = max_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5075
a61af66fc99e Initial load
duke
parents:
diff changeset
5076 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5077 // seach optimal block boundary between min_split_pos and max_split_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
5078 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5079
a61af66fc99e Initial load
duke
parents:
diff changeset
5080 if (do_loop_optimization) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5081 // Loop optimization: if a loop-end marker is found between min- and max-position,
a61af66fc99e Initial load
duke
parents:
diff changeset
5082 // then split before this loop
a61af66fc99e Initial load
duke
parents:
diff changeset
5083 int loop_end_pos = it->next_usage_exact(loopEndMarker, min_block->last_lir_instruction_id() + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5084 TRACE_LINEAR_SCAN(4, tty->print_cr(" loop optimization: loop end found at pos %d", loop_end_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5085
a61af66fc99e Initial load
duke
parents:
diff changeset
5086 assert(loop_end_pos > min_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5087 if (loop_end_pos < max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5088 // loop-end marker found between min- and max-position
a61af66fc99e Initial load
duke
parents:
diff changeset
5089 // if it is not the end marker for the same loop as the min-position, then move
a61af66fc99e Initial load
duke
parents:
diff changeset
5090 // the max-position to this loop block.
a61af66fc99e Initial load
duke
parents:
diff changeset
5091 // Desired result: uses tagged as shouldHaveRegister inside a loop cause a reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
5092 // of the interval (normally, only mustHaveRegister causes a reloading)
a61af66fc99e Initial load
duke
parents:
diff changeset
5093 BlockBegin* loop_block = allocator()->block_of_op_with_id(loop_end_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5094
a61af66fc99e Initial load
duke
parents:
diff changeset
5095 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5096 assert(loop_block != min_block, "loop_block and min_block must be different because block boundary is needed between");
a61af66fc99e Initial load
duke
parents:
diff changeset
5097
a61af66fc99e Initial load
duke
parents:
diff changeset
5098 optimal_split_pos = find_optimal_split_pos(min_block, loop_block, loop_block->last_lir_instruction_id() + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5099 if (optimal_split_pos == loop_block->last_lir_instruction_id() + 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5100 optimal_split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5101 TRACE_LINEAR_SCAN(4, tty->print_cr(" loop optimization not necessary"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5102 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5103 TRACE_LINEAR_SCAN(4, tty->print_cr(" loop optimization successful"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5104 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5105 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5106 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5107
a61af66fc99e Initial load
duke
parents:
diff changeset
5108 if (optimal_split_pos == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5109 // not calculated by loop optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
5110 optimal_split_pos = find_optimal_split_pos(min_block, max_block, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5111 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5112 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5113 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5114 TRACE_LINEAR_SCAN(4, tty->print_cr(" optimal split position: %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5115
a61af66fc99e Initial load
duke
parents:
diff changeset
5116 return optimal_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5117 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5118
a61af66fc99e Initial load
duke
parents:
diff changeset
5119
a61af66fc99e Initial load
duke
parents:
diff changeset
5120 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
5121 split an interval at the optimal position between min_split_pos and
a61af66fc99e Initial load
duke
parents:
diff changeset
5122 max_split_pos in two parts:
a61af66fc99e Initial load
duke
parents:
diff changeset
5123 1) the left part has already a location assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5124 2) the right part is sorted into to the unhandled-list
a61af66fc99e Initial load
duke
parents:
diff changeset
5125 */
a61af66fc99e Initial load
duke
parents:
diff changeset
5126 void LinearScanWalker::split_before_usage(Interval* it, int min_split_pos, int max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5127 TRACE_LINEAR_SCAN(2, tty->print ("----- splitting interval: "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5128 TRACE_LINEAR_SCAN(2, tty->print_cr(" between %d and %d", min_split_pos, max_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5129
a61af66fc99e Initial load
duke
parents:
diff changeset
5130 assert(it->from() < min_split_pos, "cannot split at start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5131 assert(current_position() < min_split_pos, "cannot split before current position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5132 assert(min_split_pos <= max_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5133 assert(max_split_pos <= it->to(), "cannot split after end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5134
a61af66fc99e Initial load
duke
parents:
diff changeset
5135 int optimal_split_pos = find_optimal_split_pos(it, min_split_pos, max_split_pos, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5136
a61af66fc99e Initial load
duke
parents:
diff changeset
5137 assert(min_split_pos <= optimal_split_pos && optimal_split_pos <= max_split_pos, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5138 assert(optimal_split_pos <= it->to(), "cannot split after end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5139 assert(optimal_split_pos > it->from(), "cannot split at start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5140
a61af66fc99e Initial load
duke
parents:
diff changeset
5141 if (optimal_split_pos == it->to() && it->next_usage(mustHaveRegister, min_split_pos) == max_jint) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5142 // the split position would be just before the end of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5143 // -> no split at all necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
5144 TRACE_LINEAR_SCAN(4, tty->print_cr(" no split necessary because optimal split position is at end of interval"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5145 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5147
a61af66fc99e Initial load
duke
parents:
diff changeset
5148 // must calculate this before the actual split is performed and before split position is moved to odd op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
5149 bool move_necessary = !allocator()->is_block_begin(optimal_split_pos) && !it->has_hole_between(optimal_split_pos - 1, optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5150
a61af66fc99e Initial load
duke
parents:
diff changeset
5151 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5152 // move position before actual instruction (odd op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5153 optimal_split_pos = (optimal_split_pos - 1) | 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5154 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5155
a61af66fc99e Initial load
duke
parents:
diff changeset
5156 TRACE_LINEAR_SCAN(4, tty->print_cr(" splitting at position %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5157 assert(allocator()->is_block_begin(optimal_split_pos) || (optimal_split_pos % 2 == 1), "split pos must be odd when not on block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
5158 assert(!allocator()->is_block_begin(optimal_split_pos) || (optimal_split_pos % 2 == 0), "split pos must be even on block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
5159
a61af66fc99e Initial load
duke
parents:
diff changeset
5160 Interval* split_part = it->split(optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5161
a61af66fc99e Initial load
duke
parents:
diff changeset
5162 allocator()->append_interval(split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5163 allocator()->copy_register_flags(it, split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5164 split_part->set_insert_move_when_activated(move_necessary);
a61af66fc99e Initial load
duke
parents:
diff changeset
5165 append_to_unhandled(unhandled_first_addr(anyKind), split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5166
a61af66fc99e Initial load
duke
parents:
diff changeset
5167 TRACE_LINEAR_SCAN(2, tty->print_cr(" split interval in two parts (insert_move_when_activated: %d)", move_necessary));
a61af66fc99e Initial load
duke
parents:
diff changeset
5168 TRACE_LINEAR_SCAN(2, tty->print (" "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5169 TRACE_LINEAR_SCAN(2, tty->print (" "); split_part->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5170 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5171
a61af66fc99e Initial load
duke
parents:
diff changeset
5172 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
5173 split an interval at the optimal position between min_split_pos and
a61af66fc99e Initial load
duke
parents:
diff changeset
5174 max_split_pos in two parts:
a61af66fc99e Initial load
duke
parents:
diff changeset
5175 1) the left part has already a location assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5176 2) the right part is always on the stack and therefore ignored in further processing
a61af66fc99e Initial load
duke
parents:
diff changeset
5177 */
a61af66fc99e Initial load
duke
parents:
diff changeset
5178 void LinearScanWalker::split_for_spilling(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5179 // calculate allowed range of splitting position
a61af66fc99e Initial load
duke
parents:
diff changeset
5180 int max_split_pos = current_position();
a61af66fc99e Initial load
duke
parents:
diff changeset
5181 int min_split_pos = MAX2(it->previous_usage(shouldHaveRegister, max_split_pos) + 1, it->from());
a61af66fc99e Initial load
duke
parents:
diff changeset
5182
a61af66fc99e Initial load
duke
parents:
diff changeset
5183 TRACE_LINEAR_SCAN(2, tty->print ("----- splitting and spilling interval: "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5184 TRACE_LINEAR_SCAN(2, tty->print_cr(" between %d and %d", min_split_pos, max_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5185
a61af66fc99e Initial load
duke
parents:
diff changeset
5186 assert(it->state() == activeState, "why spill interval that is not active?");
a61af66fc99e Initial load
duke
parents:
diff changeset
5187 assert(it->from() <= min_split_pos, "cannot split before start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5188 assert(min_split_pos <= max_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5189 assert(max_split_pos < it->to(), "cannot split at end end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5190 assert(current_position() < it->to(), "interval must not end before current position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5191
a61af66fc99e Initial load
duke
parents:
diff changeset
5192 if (min_split_pos == it->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5193 // the whole interval is never used, so spill it entirely to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
5194 TRACE_LINEAR_SCAN(2, tty->print_cr(" spilling entire interval because split pos is at beginning of interval"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5195 assert(it->first_usage(shouldHaveRegister) > current_position(), "interval must not have use position before current_position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5196
a61af66fc99e Initial load
duke
parents:
diff changeset
5197 allocator()->assign_spill_slot(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5198 allocator()->change_spill_state(it, min_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5199
a61af66fc99e Initial load
duke
parents:
diff changeset
5200 // Also kick parent intervals out of register to memory when they have no use
a61af66fc99e Initial load
duke
parents:
diff changeset
5201 // position. This avoids short interval in register surrounded by intervals in
a61af66fc99e Initial load
duke
parents:
diff changeset
5202 // memory -> avoid useless moves from memory to register and back
a61af66fc99e Initial load
duke
parents:
diff changeset
5203 Interval* parent = it;
a61af66fc99e Initial load
duke
parents:
diff changeset
5204 while (parent != NULL && parent->is_split_child()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5205 parent = parent->split_child_before_op_id(parent->from());
a61af66fc99e Initial load
duke
parents:
diff changeset
5206
a61af66fc99e Initial load
duke
parents:
diff changeset
5207 if (parent->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5208 if (parent->first_usage(shouldHaveRegister) == max_jint) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5209 // parent is never used, so kick it out of its assigned register
a61af66fc99e Initial load
duke
parents:
diff changeset
5210 TRACE_LINEAR_SCAN(4, tty->print_cr(" kicking out interval %d out of its register because it is never used", parent->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5211 allocator()->assign_spill_slot(parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
5212 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5213 // do not go further back because the register is actually used by the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5214 parent = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
5215 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5217 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5218
a61af66fc99e Initial load
duke
parents:
diff changeset
5219 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5220 // search optimal split pos, split interval and spill only the right hand part
a61af66fc99e Initial load
duke
parents:
diff changeset
5221 int optimal_split_pos = find_optimal_split_pos(it, min_split_pos, max_split_pos, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5222
a61af66fc99e Initial load
duke
parents:
diff changeset
5223 assert(min_split_pos <= optimal_split_pos && optimal_split_pos <= max_split_pos, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5224 assert(optimal_split_pos < it->to(), "cannot split at end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5225 assert(optimal_split_pos >= it->from(), "cannot split before start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5226
a61af66fc99e Initial load
duke
parents:
diff changeset
5227 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5228 // move position before actual instruction (odd op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5229 optimal_split_pos = (optimal_split_pos - 1) | 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5230 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5231
a61af66fc99e Initial load
duke
parents:
diff changeset
5232 TRACE_LINEAR_SCAN(4, tty->print_cr(" splitting at position %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5233 assert(allocator()->is_block_begin(optimal_split_pos) || (optimal_split_pos % 2 == 1), "split pos must be odd when not on block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
5234 assert(!allocator()->is_block_begin(optimal_split_pos) || (optimal_split_pos % 2 == 0), "split pos must be even on block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
5235
a61af66fc99e Initial load
duke
parents:
diff changeset
5236 Interval* spilled_part = it->split(optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5237 allocator()->append_interval(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5238 allocator()->assign_spill_slot(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5239 allocator()->change_spill_state(spilled_part, optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5240
a61af66fc99e Initial load
duke
parents:
diff changeset
5241 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5242 TRACE_LINEAR_SCAN(4, tty->print_cr(" inserting move from interval %d to %d", it->reg_num(), spilled_part->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5243 insert_move(optimal_split_pos, it, spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5244 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5245
a61af66fc99e Initial load
duke
parents:
diff changeset
5246 // the current_split_child is needed later when moves are inserted for reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
5247 assert(spilled_part->current_split_child() == it, "overwriting wrong current_split_child");
a61af66fc99e Initial load
duke
parents:
diff changeset
5248 spilled_part->make_current_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
5249
a61af66fc99e Initial load
duke
parents:
diff changeset
5250 TRACE_LINEAR_SCAN(2, tty->print_cr(" split interval in two parts"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5251 TRACE_LINEAR_SCAN(2, tty->print (" "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5252 TRACE_LINEAR_SCAN(2, tty->print (" "); spilled_part->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5253 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5254 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5255
a61af66fc99e Initial load
duke
parents:
diff changeset
5256
a61af66fc99e Initial load
duke
parents:
diff changeset
5257 void LinearScanWalker::split_stack_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5258 int min_split_pos = current_position() + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5259 int max_split_pos = MIN2(it->first_usage(shouldHaveRegister), it->to());
a61af66fc99e Initial load
duke
parents:
diff changeset
5260
a61af66fc99e Initial load
duke
parents:
diff changeset
5261 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5262 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5263
a61af66fc99e Initial load
duke
parents:
diff changeset
5264 void LinearScanWalker::split_when_partial_register_available(Interval* it, int register_available_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5265 int min_split_pos = MAX2(it->previous_usage(shouldHaveRegister, register_available_until), it->from() + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5266 int max_split_pos = register_available_until;
a61af66fc99e Initial load
duke
parents:
diff changeset
5267
a61af66fc99e Initial load
duke
parents:
diff changeset
5268 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5269 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5270
a61af66fc99e Initial load
duke
parents:
diff changeset
5271 void LinearScanWalker::split_and_spill_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5272 assert(it->state() == activeState || it->state() == inactiveState, "other states not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
5273
a61af66fc99e Initial load
duke
parents:
diff changeset
5274 int current_pos = current_position();
a61af66fc99e Initial load
duke
parents:
diff changeset
5275 if (it->state() == inactiveState) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5276 // the interval is currently inactive, so no spill slot is needed for now.
a61af66fc99e Initial load
duke
parents:
diff changeset
5277 // when the split part is activated, the interval has a new chance to get a register,
a61af66fc99e Initial load
duke
parents:
diff changeset
5278 // so in the best case no stack slot is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
5279 assert(it->has_hole_between(current_pos - 1, current_pos + 1), "interval can not be inactive otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5280 split_before_usage(it, current_pos + 1, current_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5281
a61af66fc99e Initial load
duke
parents:
diff changeset
5282 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5283 // search the position where the interval must have a register and split
a61af66fc99e Initial load
duke
parents:
diff changeset
5284 // at the optimal position before.
a61af66fc99e Initial load
duke
parents:
diff changeset
5285 // The new created part is added to the unhandled list and will get a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5286 // when it is activated
a61af66fc99e Initial load
duke
parents:
diff changeset
5287 int min_split_pos = current_pos + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5288 int max_split_pos = MIN2(it->next_usage(mustHaveRegister, min_split_pos), it->to());
a61af66fc99e Initial load
duke
parents:
diff changeset
5289
a61af66fc99e Initial load
duke
parents:
diff changeset
5290 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5291
a61af66fc99e Initial load
duke
parents:
diff changeset
5292 assert(it->next_usage(mustHaveRegister, current_pos) == max_jint, "the remaining part is spilled to stack and therefore has no register");
a61af66fc99e Initial load
duke
parents:
diff changeset
5293 split_for_spilling(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5294 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5295 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5296
a61af66fc99e Initial load
duke
parents:
diff changeset
5297
a61af66fc99e Initial load
duke
parents:
diff changeset
5298 int LinearScanWalker::find_free_reg(int reg_needed_until, int interval_to, int hint_reg, int ignore_reg, bool* need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5299 int min_full_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5300 int max_partial_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5301
a61af66fc99e Initial load
duke
parents:
diff changeset
5302 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5303 if (i == ignore_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5304 // this register must be ignored
a61af66fc99e Initial load
duke
parents:
diff changeset
5305
a61af66fc99e Initial load
duke
parents:
diff changeset
5306 } else if (_use_pos[i] >= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5307 // this register is free for the full interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5308 if (min_full_reg == any_reg || i == hint_reg || (_use_pos[i] < _use_pos[min_full_reg] && min_full_reg != hint_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5309 min_full_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5310 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5311 } else if (_use_pos[i] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5312 // this register is at least free until reg_needed_until
a61af66fc99e Initial load
duke
parents:
diff changeset
5313 if (max_partial_reg == any_reg || i == hint_reg || (_use_pos[i] > _use_pos[max_partial_reg] && max_partial_reg != hint_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5314 max_partial_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5315 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5316 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5317 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5318
a61af66fc99e Initial load
duke
parents:
diff changeset
5319 if (min_full_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5320 return min_full_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5321 } else if (max_partial_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5322 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5323 return max_partial_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5324 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5325 return any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5326 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5327 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5328
a61af66fc99e Initial load
duke
parents:
diff changeset
5329 int LinearScanWalker::find_free_double_reg(int reg_needed_until, int interval_to, int hint_reg, bool* need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5330 assert((_last_reg - _first_reg + 1) % 2 == 0, "adjust algorithm");
a61af66fc99e Initial load
duke
parents:
diff changeset
5331
a61af66fc99e Initial load
duke
parents:
diff changeset
5332 int min_full_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5333 int max_partial_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5334
a61af66fc99e Initial load
duke
parents:
diff changeset
5335 for (int i = _first_reg; i < _last_reg; i+=2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5336 if (_use_pos[i] >= interval_to && _use_pos[i + 1] >= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5337 // this register is free for the full interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5338 if (min_full_reg == any_reg || i == hint_reg || (_use_pos[i] < _use_pos[min_full_reg] && min_full_reg != hint_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5339 min_full_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5340 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5341 } else if (_use_pos[i] > reg_needed_until && _use_pos[i + 1] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5342 // this register is at least free until reg_needed_until
a61af66fc99e Initial load
duke
parents:
diff changeset
5343 if (max_partial_reg == any_reg || i == hint_reg || (_use_pos[i] > _use_pos[max_partial_reg] && max_partial_reg != hint_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5344 max_partial_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5345 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5346 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5347 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5348
a61af66fc99e Initial load
duke
parents:
diff changeset
5349 if (min_full_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5350 return min_full_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5351 } else if (max_partial_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5352 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5353 return max_partial_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5354 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5355 return any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5356 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5357 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5358
a61af66fc99e Initial load
duke
parents:
diff changeset
5359
a61af66fc99e Initial load
duke
parents:
diff changeset
5360 bool LinearScanWalker::alloc_free_reg(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5361 TRACE_LINEAR_SCAN(2, tty->print("trying to find free register for "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5362
a61af66fc99e Initial load
duke
parents:
diff changeset
5363 init_use_lists(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5364 free_exclude_active_fixed();
a61af66fc99e Initial load
duke
parents:
diff changeset
5365 free_exclude_active_any();
a61af66fc99e Initial load
duke
parents:
diff changeset
5366 free_collect_inactive_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5367 free_collect_inactive_any(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5368 // free_collect_unhandled(fixedKind, cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5369 assert(unhandled_first(fixedKind) == Interval::end(), "must not have unhandled fixed intervals because all fixed intervals have a use at position 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
5370
a61af66fc99e Initial load
duke
parents:
diff changeset
5371 // _use_pos contains the start of the next interval that has this register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5372 // (either as a fixed register or a normal allocated register in the past)
a61af66fc99e Initial load
duke
parents:
diff changeset
5373 // only intervals overlapping with cur are processed, non-overlapping invervals can be ignored safely
a61af66fc99e Initial load
duke
parents:
diff changeset
5374 TRACE_LINEAR_SCAN(4, tty->print_cr(" state of registers:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5375 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]));
a61af66fc99e Initial load
duke
parents:
diff changeset
5376
a61af66fc99e Initial load
duke
parents:
diff changeset
5377 int hint_reg, hint_regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5378 Interval* register_hint = cur->register_hint();
a61af66fc99e Initial load
duke
parents:
diff changeset
5379 if (register_hint != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5380 hint_reg = register_hint->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
5381 hint_regHi = register_hint->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
5382
a61af66fc99e Initial load
duke
parents:
diff changeset
5383 if (allocator()->is_precolored_cpu_interval(register_hint)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5384 assert(hint_reg != any_reg && hint_regHi == any_reg, "must be for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
5385 hint_regHi = hint_reg + 1; // connect e.g. eax-edx
a61af66fc99e Initial load
duke
parents:
diff changeset
5386 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5387 TRACE_LINEAR_SCAN(4, tty->print(" hint registers %d, %d from interval ", hint_reg, hint_regHi); register_hint->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5388
a61af66fc99e Initial load
duke
parents:
diff changeset
5389 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5390 hint_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5391 hint_regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5392 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5393 assert(hint_reg == any_reg || hint_reg != hint_regHi, "hint reg and regHi equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
5394 assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned to interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5395
a61af66fc99e Initial load
duke
parents:
diff changeset
5396 // the register must be free at least until this position
a61af66fc99e Initial load
duke
parents:
diff changeset
5397 int reg_needed_until = cur->from() + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5398 int interval_to = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5399
a61af66fc99e Initial load
duke
parents:
diff changeset
5400 bool need_split = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5401 int split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5402 int reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5403 int regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5404
a61af66fc99e Initial load
duke
parents:
diff changeset
5405 if (_adjacent_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5406 reg = find_free_double_reg(reg_needed_until, interval_to, hint_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5407 regHi = reg + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5408 if (reg == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5409 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5410 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5411 split_pos = MIN2(_use_pos[reg], _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5412
a61af66fc99e Initial load
duke
parents:
diff changeset
5413 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5414 reg = find_free_reg(reg_needed_until, interval_to, hint_reg, any_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5415 if (reg == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5416 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5417 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5418 split_pos = _use_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5419
a61af66fc99e Initial load
duke
parents:
diff changeset
5420 if (_num_phys_regs == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5421 regHi = find_free_reg(reg_needed_until, interval_to, hint_regHi, reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5422
a61af66fc99e Initial load
duke
parents:
diff changeset
5423 if (_use_pos[reg] < interval_to && regHi == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5424 // do not split interval if only one register can be assigned until the split pos
a61af66fc99e Initial load
duke
parents:
diff changeset
5425 // (when one register is found for the whole interval, split&spill is only
a61af66fc99e Initial load
duke
parents:
diff changeset
5426 // performed for the hi register)
a61af66fc99e Initial load
duke
parents:
diff changeset
5427 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5428
a61af66fc99e Initial load
duke
parents:
diff changeset
5429 } else if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5430 split_pos = MIN2(split_pos, _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5431
a61af66fc99e Initial load
duke
parents:
diff changeset
5432 // sort register numbers to prevent e.g. a move from eax,ebx to ebx,eax
a61af66fc99e Initial load
duke
parents:
diff changeset
5433 if (reg > regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5434 int temp = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5435 reg = regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5436 regHi = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
5437 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5438 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5439 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5440 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5441
a61af66fc99e Initial load
duke
parents:
diff changeset
5442 cur->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5443 TRACE_LINEAR_SCAN(2, tty->print_cr("selected register %d, %d", reg, regHi));
a61af66fc99e Initial load
duke
parents:
diff changeset
5444
a61af66fc99e Initial load
duke
parents:
diff changeset
5445 assert(split_pos > 0, "invalid split_pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
5446 if (need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5447 // register not available for full interval, so split it
a61af66fc99e Initial load
duke
parents:
diff changeset
5448 split_when_partial_register_available(cur, split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5449 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5450
a61af66fc99e Initial load
duke
parents:
diff changeset
5451 // only return true if interval is completely assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5452 return _num_phys_regs == 1 || regHi != any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5453 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5454
a61af66fc99e Initial load
duke
parents:
diff changeset
5455
a61af66fc99e Initial load
duke
parents:
diff changeset
5456 int LinearScanWalker::find_locked_reg(int reg_needed_until, int interval_to, int hint_reg, int ignore_reg, bool* need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5457 int max_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5458
a61af66fc99e Initial load
duke
parents:
diff changeset
5459 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5460 if (i == ignore_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5461 // this register must be ignored
a61af66fc99e Initial load
duke
parents:
diff changeset
5462
a61af66fc99e Initial load
duke
parents:
diff changeset
5463 } else if (_use_pos[i] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5464 if (max_reg == any_reg || i == hint_reg || (_use_pos[i] > _use_pos[max_reg] && max_reg != hint_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5465 max_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5466 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5467 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5468 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5469
a61af66fc99e Initial load
duke
parents:
diff changeset
5470 if (max_reg != any_reg && _block_pos[max_reg] <= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5471 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5472 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5473
a61af66fc99e Initial load
duke
parents:
diff changeset
5474 return max_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5475 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5476
a61af66fc99e Initial load
duke
parents:
diff changeset
5477 int LinearScanWalker::find_locked_double_reg(int reg_needed_until, int interval_to, int hint_reg, bool* need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5478 assert((_last_reg - _first_reg + 1) % 2 == 0, "adjust algorithm");
a61af66fc99e Initial load
duke
parents:
diff changeset
5479
a61af66fc99e Initial load
duke
parents:
diff changeset
5480 int max_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5481
a61af66fc99e Initial load
duke
parents:
diff changeset
5482 for (int i = _first_reg; i < _last_reg; i+=2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5483 if (_use_pos[i] > reg_needed_until && _use_pos[i + 1] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5484 if (max_reg == any_reg || _use_pos[i] > _use_pos[max_reg]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5485 max_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5486 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5489
a61af66fc99e Initial load
duke
parents:
diff changeset
5490 if (_block_pos[max_reg] <= interval_to || _block_pos[max_reg + 1] <= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5491 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5492 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5493
a61af66fc99e Initial load
duke
parents:
diff changeset
5494 return max_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5495 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5496
a61af66fc99e Initial load
duke
parents:
diff changeset
5497 void LinearScanWalker::split_and_spill_intersecting_intervals(int reg, int regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5498 assert(reg != any_reg, "no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5499
a61af66fc99e Initial load
duke
parents:
diff changeset
5500 for (int i = 0; i < _spill_intervals[reg]->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5501 Interval* it = _spill_intervals[reg]->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5502 remove_from_list(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5503 split_and_spill_interval(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5504 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5505
a61af66fc99e Initial load
duke
parents:
diff changeset
5506 if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5507 IntervalList* processed = _spill_intervals[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5508 for (int i = 0; i < _spill_intervals[regHi]->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5509 Interval* it = _spill_intervals[regHi]->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5510 if (processed->index_of(it) == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5511 remove_from_list(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5512 split_and_spill_interval(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5513 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5514 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5515 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5516 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5517
a61af66fc99e Initial load
duke
parents:
diff changeset
5518
a61af66fc99e Initial load
duke
parents:
diff changeset
5519 // Split an Interval and spill it to memory so that cur can be placed in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5520 void LinearScanWalker::alloc_locked_reg(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5521 TRACE_LINEAR_SCAN(2, tty->print("need to split and spill to get register for "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5522
a61af66fc99e Initial load
duke
parents:
diff changeset
5523 // collect current usage of registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5524 init_use_lists(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5525 spill_exclude_active_fixed();
a61af66fc99e Initial load
duke
parents:
diff changeset
5526 // spill_block_unhandled_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5527 assert(unhandled_first(fixedKind) == Interval::end(), "must not have unhandled fixed intervals because all fixed intervals have a use at position 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
5528 spill_block_inactive_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5529 spill_collect_active_any();
a61af66fc99e Initial load
duke
parents:
diff changeset
5530 spill_collect_inactive_any(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5531
a61af66fc99e Initial load
duke
parents:
diff changeset
5532 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
5533 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5534 tty->print_cr(" state of registers:");
a61af66fc99e Initial load
duke
parents:
diff changeset
5535 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5536 tty->print(" reg %d: use_pos: %d, block_pos: %d, intervals: ", i, _use_pos[i], _block_pos[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5537 for (int j = 0; j < _spill_intervals[i]->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5538 tty->print("%d ", _spill_intervals[i]->at(j)->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
5539 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5540 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5541 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5542 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5543 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5544
a61af66fc99e Initial load
duke
parents:
diff changeset
5545 // the register must be free at least until this position
a61af66fc99e Initial load
duke
parents:
diff changeset
5546 int reg_needed_until = MIN2(cur->first_usage(mustHaveRegister), cur->from() + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5547 int interval_to = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5548 assert (reg_needed_until > 0 && reg_needed_until < max_jint, "interval has no use");
a61af66fc99e Initial load
duke
parents:
diff changeset
5549
a61af66fc99e Initial load
duke
parents:
diff changeset
5550 int split_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
5551 int use_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
5552 bool need_split = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5553 int reg, regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5554
a61af66fc99e Initial load
duke
parents:
diff changeset
5555 if (_adjacent_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5556 reg = find_locked_double_reg(reg_needed_until, interval_to, any_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5557 regHi = reg + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5558
a61af66fc99e Initial load
duke
parents:
diff changeset
5559 if (reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5560 use_pos = MIN2(_use_pos[reg], _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5561 split_pos = MIN2(_block_pos[reg], _block_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5562 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5563 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5564 reg = find_locked_reg(reg_needed_until, interval_to, any_reg, cur->assigned_reg(), &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5565 regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5566
a61af66fc99e Initial load
duke
parents:
diff changeset
5567 if (reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5568 use_pos = _use_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5569 split_pos = _block_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5570
a61af66fc99e Initial load
duke
parents:
diff changeset
5571 if (_num_phys_regs == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5572 if (cur->assigned_reg() != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5573 regHi = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5574 reg = cur->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
5575 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5576 regHi = find_locked_reg(reg_needed_until, interval_to, any_reg, reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5577 if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5578 use_pos = MIN2(use_pos, _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5579 split_pos = MIN2(split_pos, _block_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5580 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5581 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5582
a61af66fc99e Initial load
duke
parents:
diff changeset
5583 if (regHi != any_reg && reg > regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5584 // sort register numbers to prevent e.g. a move from eax,ebx to ebx,eax
a61af66fc99e Initial load
duke
parents:
diff changeset
5585 int temp = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5586 reg = regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5587 regHi = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
5588 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5589 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5590 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5591 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5592
a61af66fc99e Initial load
duke
parents:
diff changeset
5593 if (reg == any_reg || (_num_phys_regs == 2 && regHi == any_reg) || use_pos <= cur->first_usage(mustHaveRegister)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5594 // the first use of cur is later than the spilling position -> spill cur
a61af66fc99e Initial load
duke
parents:
diff changeset
5595 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));
a61af66fc99e Initial load
duke
parents:
diff changeset
5596
a61af66fc99e Initial load
duke
parents:
diff changeset
5597 if (cur->first_usage(mustHaveRegister) <= cur->from() + 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5598 assert(false, "cannot spill interval that is used in first instruction (possible reason: no register found)");
a61af66fc99e Initial load
duke
parents:
diff changeset
5599 // assign a reasonable register and do a bailout in product mode to avoid errors
a61af66fc99e Initial load
duke
parents:
diff changeset
5600 allocator()->assign_spill_slot(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5601 BAILOUT("LinearScan: no register found");
a61af66fc99e Initial load
duke
parents:
diff changeset
5602 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5603
a61af66fc99e Initial load
duke
parents:
diff changeset
5604 split_and_spill_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5605 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5606 TRACE_LINEAR_SCAN(4, tty->print_cr("decided to use register %d, %d", reg, regHi));
a61af66fc99e Initial load
duke
parents:
diff changeset
5607 assert(reg != any_reg && (_num_phys_regs == 1 || regHi != any_reg), "no register found");
a61af66fc99e Initial load
duke
parents:
diff changeset
5608 assert(split_pos > 0, "invalid split_pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
5609 assert(need_split == false || split_pos > cur->from(), "splitting interval at from");
a61af66fc99e Initial load
duke
parents:
diff changeset
5610
a61af66fc99e Initial load
duke
parents:
diff changeset
5611 cur->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5612 if (need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5613 // register not available for full interval, so split it
a61af66fc99e Initial load
duke
parents:
diff changeset
5614 split_when_partial_register_available(cur, split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5615 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5616
a61af66fc99e Initial load
duke
parents:
diff changeset
5617 // perform splitting and spilling for all affected intervalls
a61af66fc99e Initial load
duke
parents:
diff changeset
5618 split_and_spill_intersecting_intervals(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5619 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5620 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5621
a61af66fc99e Initial load
duke
parents:
diff changeset
5622 bool LinearScanWalker::no_allocation_possible(Interval* cur) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
5623 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
5624 // fast calculation of intervals that can never get a register because the
a61af66fc99e Initial load
duke
parents:
diff changeset
5625 // the next instruction is a call that blocks all registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5626 // Note: this does not work if callee-saved registers are available (e.g. on Sparc)
a61af66fc99e Initial load
duke
parents:
diff changeset
5627
a61af66fc99e Initial load
duke
parents:
diff changeset
5628 // check if this interval is the result of a split operation
a61af66fc99e Initial load
duke
parents:
diff changeset
5629 // (an interval got a register until this position)
a61af66fc99e Initial load
duke
parents:
diff changeset
5630 int pos = cur->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
5631 if ((pos & 1) == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5632 // the current instruction is a call that blocks all registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5633 if (pos < allocator()->max_lir_op_id() && allocator()->has_call(pos + 1)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5634 TRACE_LINEAR_SCAN(4, tty->print_cr(" free register cannot be available because all registers blocked by following call"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5635
a61af66fc99e Initial load
duke
parents:
diff changeset
5636 // safety check that there is really no register available
a61af66fc99e Initial load
duke
parents:
diff changeset
5637 assert(alloc_free_reg(cur) == false, "found a register for this interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5638 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5639 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5640
a61af66fc99e Initial load
duke
parents:
diff changeset
5641 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5642 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5643 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5645
a61af66fc99e Initial load
duke
parents:
diff changeset
5646 void LinearScanWalker::init_vars_for_alloc(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5647 BasicType type = cur->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
5648 _num_phys_regs = LinearScan::num_physical_regs(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
5649 _adjacent_regs = LinearScan::requires_adjacent_regs(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
5650
a61af66fc99e Initial load
duke
parents:
diff changeset
5651 if (pd_init_regs_for_alloc(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5652 // the appropriate register range was selected.
a61af66fc99e Initial load
duke
parents:
diff changeset
5653 } else if (type == T_FLOAT || type == T_DOUBLE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5654 _first_reg = pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5655 _last_reg = pd_last_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5656 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5657 _first_reg = pd_first_cpu_reg;
2002
ac637b7220d1 6985015: C1 needs to support compressed oops
iveresov
parents: 1972
diff changeset
5658 _last_reg = FrameMap::last_cpu_reg();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
5659 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5660
a61af66fc99e Initial load
duke
parents:
diff changeset
5661 assert(0 <= _first_reg && _first_reg < LinearScan::nof_regs, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5662 assert(0 <= _last_reg && _last_reg < LinearScan::nof_regs, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5663 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5664
a61af66fc99e Initial load
duke
parents:
diff changeset
5665
a61af66fc99e Initial load
duke
parents:
diff changeset
5666 bool LinearScanWalker::is_move(LIR_Op* op, Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5667 if (op->code() != lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5668 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5669 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5670 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5671
a61af66fc99e Initial load
duke
parents:
diff changeset
5672 LIR_Opr in = ((LIR_Op1*)op)->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5673 LIR_Opr res = ((LIR_Op1*)op)->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5674 return in->is_virtual() && res->is_virtual() && in->vreg_number() == from->reg_num() && res->vreg_number() == to->reg_num();
a61af66fc99e Initial load
duke
parents:
diff changeset
5675 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5676
a61af66fc99e Initial load
duke
parents:
diff changeset
5677 // optimization (especially for phi functions of nested loops):
a61af66fc99e Initial load
duke
parents:
diff changeset
5678 // assign same spill slot to non-intersecting intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
5679 void LinearScanWalker::combine_spilled_intervals(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5680 if (cur->is_split_child()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5681 // optimization is only suitable for split parents
a61af66fc99e Initial load
duke
parents:
diff changeset
5682 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5683 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5684
a61af66fc99e Initial load
duke
parents:
diff changeset
5685 Interval* register_hint = cur->register_hint(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5686 if (register_hint == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5687 // cur is not the target of a move, otherwise register_hint would be set
a61af66fc99e Initial load
duke
parents:
diff changeset
5688 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5689 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5690 assert(register_hint->is_split_parent(), "register hint must be split parent");
a61af66fc99e Initial load
duke
parents:
diff changeset
5691
a61af66fc99e Initial load
duke
parents:
diff changeset
5692 if (cur->spill_state() != noOptimization || register_hint->spill_state() != noOptimization) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5693 // combining the stack slots for intervals where spill move optimization is applied
a61af66fc99e Initial load
duke
parents:
diff changeset
5694 // is not benefitial and would cause problems
a61af66fc99e Initial load
duke
parents:
diff changeset
5695 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5696 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5697
a61af66fc99e Initial load
duke
parents:
diff changeset
5698 int begin_pos = cur->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
5699 int end_pos = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5700 if (end_pos > allocator()->max_lir_op_id() || (begin_pos & 1) != 0 || (end_pos & 1) != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5701 // safety check that lir_op_with_id is allowed
a61af66fc99e Initial load
duke
parents:
diff changeset
5702 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5703 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5704
a61af66fc99e Initial load
duke
parents:
diff changeset
5705 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)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5706 // cur and register_hint are not connected with two moves
a61af66fc99e Initial load
duke
parents:
diff changeset
5707 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5708 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5709
a61af66fc99e Initial load
duke
parents:
diff changeset
5710 Interval* begin_hint = register_hint->split_child_at_op_id(begin_pos, LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
5711 Interval* end_hint = register_hint->split_child_at_op_id(end_pos, LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
5712 if (begin_hint == end_hint || begin_hint->to() != begin_pos || end_hint->from() != end_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5713 // register_hint must be split, otherwise the re-writing of use positions does not work
a61af66fc99e Initial load
duke
parents:
diff changeset
5714 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5715 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5716
a61af66fc99e Initial load
duke
parents:
diff changeset
5717 assert(begin_hint->assigned_reg() != any_reg, "must have register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5718 assert(end_hint->assigned_reg() == any_reg, "must not have register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5719 assert(cur->first_usage(mustHaveRegister) == begin_pos, "must have use position at begin of interval because of move");
a61af66fc99e Initial load
duke
parents:
diff changeset
5720 assert(end_hint->first_usage(mustHaveRegister) == end_pos, "must have use position at begin of interval because of move");
a61af66fc99e Initial load
duke
parents:
diff changeset
5721
a61af66fc99e Initial load
duke
parents:
diff changeset
5722 if (begin_hint->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5723 // register_hint is not spilled at begin_pos, so it would not be benefitial to immediately spill cur
a61af66fc99e Initial load
duke
parents:
diff changeset
5724 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5725 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5726 assert(register_hint->canonical_spill_slot() != -1, "must be set when part of interval was spilled");
a61af66fc99e Initial load
duke
parents:
diff changeset
5727
a61af66fc99e Initial load
duke
parents:
diff changeset
5728 // modify intervals such that cur gets the same stack slot as register_hint
a61af66fc99e Initial load
duke
parents:
diff changeset
5729 // delete use positions to prevent the intervals to get a register at beginning
a61af66fc99e Initial load
duke
parents:
diff changeset
5730 cur->set_canonical_spill_slot(register_hint->canonical_spill_slot());
a61af66fc99e Initial load
duke
parents:
diff changeset
5731 cur->remove_first_use_pos();
a61af66fc99e Initial load
duke
parents:
diff changeset
5732 end_hint->remove_first_use_pos();
a61af66fc99e Initial load
duke
parents:
diff changeset
5733 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5734
a61af66fc99e Initial load
duke
parents:
diff changeset
5735
a61af66fc99e Initial load
duke
parents:
diff changeset
5736 // allocate a physical register or memory location to an interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5737 bool LinearScanWalker::activate_current() {
a61af66fc99e Initial load
duke
parents:
diff changeset
5738 Interval* cur = current();
a61af66fc99e Initial load
duke
parents:
diff changeset
5739 bool result = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5740
a61af66fc99e Initial load
duke
parents:
diff changeset
5741 TRACE_LINEAR_SCAN(2, tty->print ("+++++ activating interval "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5742 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5743
a61af66fc99e Initial load
duke
parents:
diff changeset
5744 if (cur->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5745 // activating an interval that has a stack slot assigned -> split it at first use position
a61af66fc99e Initial load
duke
parents:
diff changeset
5746 // used for method parameters
a61af66fc99e Initial load
duke
parents:
diff changeset
5747 TRACE_LINEAR_SCAN(4, tty->print_cr(" interval has spill slot assigned (method parameter) -> split it before first use"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5748
a61af66fc99e Initial load
duke
parents:
diff changeset
5749 split_stack_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5750 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5751
a61af66fc99e Initial load
duke
parents:
diff changeset
5752 } else if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::must_start_in_memory)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5753 // activating an interval that must start in a stack slot, but may get a register later
a61af66fc99e Initial load
duke
parents:
diff changeset
5754 // used for lir_roundfp: rounding is done by store to stack and reload later
a61af66fc99e Initial load
duke
parents:
diff changeset
5755 TRACE_LINEAR_SCAN(4, tty->print_cr(" interval must start in stack slot -> split it before first use"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5756 assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5757
a61af66fc99e Initial load
duke
parents:
diff changeset
5758 allocator()->assign_spill_slot(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5759 split_stack_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5760 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5761
a61af66fc99e Initial load
duke
parents:
diff changeset
5762 } else if (cur->assigned_reg() == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5763 // interval has not assigned register -> normal allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
5764 // (this is the normal case for most intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
5765 TRACE_LINEAR_SCAN(4, tty->print_cr(" normal allocation of register"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5766
a61af66fc99e Initial load
duke
parents:
diff changeset
5767 // assign same spill slot to non-intersecting intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
5768 combine_spilled_intervals(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5769
a61af66fc99e Initial load
duke
parents:
diff changeset
5770 init_vars_for_alloc(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5771 if (no_allocation_possible(cur) || !alloc_free_reg(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5772 // no empty register available.
a61af66fc99e Initial load
duke
parents:
diff changeset
5773 // split and spill another interval so that this interval gets a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5774 alloc_locked_reg(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5775 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5776
a61af66fc99e Initial load
duke
parents:
diff changeset
5777 // spilled intervals need not be move to active-list
a61af66fc99e Initial load
duke
parents:
diff changeset
5778 if (cur->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5779 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5780 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5781 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5782
a61af66fc99e Initial load
duke
parents:
diff changeset
5783 // load spilled values that become active from stack slot to register
a61af66fc99e Initial load
duke
parents:
diff changeset
5784 if (cur->insert_move_when_activated()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5785 assert(cur->is_split_child(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
5786 assert(cur->current_split_child() != NULL, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
5787 assert(cur->current_split_child()->reg_num() != cur->reg_num(), "cannot insert move between same interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5788 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5789
a61af66fc99e Initial load
duke
parents:
diff changeset
5790 insert_move(cur->from(), cur->current_split_child(), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5791 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5792 cur->make_current_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
5793
a61af66fc99e Initial load
duke
parents:
diff changeset
5794 return result; // true = interval is moved to active list
a61af66fc99e Initial load
duke
parents:
diff changeset
5795 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5796
a61af66fc99e Initial load
duke
parents:
diff changeset
5797
a61af66fc99e Initial load
duke
parents:
diff changeset
5798 // Implementation of EdgeMoveOptimizer
a61af66fc99e Initial load
duke
parents:
diff changeset
5799
a61af66fc99e Initial load
duke
parents:
diff changeset
5800 EdgeMoveOptimizer::EdgeMoveOptimizer() :
a61af66fc99e Initial load
duke
parents:
diff changeset
5801 _edge_instructions(4),
a61af66fc99e Initial load
duke
parents:
diff changeset
5802 _edge_instructions_idx(4)
a61af66fc99e Initial load
duke
parents:
diff changeset
5803 {
a61af66fc99e Initial load
duke
parents:
diff changeset
5804 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5805
a61af66fc99e Initial load
duke
parents:
diff changeset
5806 void EdgeMoveOptimizer::optimize(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5807 EdgeMoveOptimizer optimizer = EdgeMoveOptimizer();
a61af66fc99e Initial load
duke
parents:
diff changeset
5808
a61af66fc99e Initial load
duke
parents:
diff changeset
5809 // ignore the first block in the list (index 0 is not processed)
a61af66fc99e Initial load
duke
parents:
diff changeset
5810 for (int i = code->length() - 1; i >= 1; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5811 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5812
a61af66fc99e Initial load
duke
parents:
diff changeset
5813 if (block->number_of_preds() > 1 && !block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5814 optimizer.optimize_moves_at_block_end(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
5815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5816 if (block->number_of_sux() == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5817 optimizer.optimize_moves_at_block_begin(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
5818 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5819 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5820 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5821
a61af66fc99e Initial load
duke
parents:
diff changeset
5822
a61af66fc99e Initial load
duke
parents:
diff changeset
5823 // clear all internal data structures
a61af66fc99e Initial load
duke
parents:
diff changeset
5824 void EdgeMoveOptimizer::init_instructions() {
a61af66fc99e Initial load
duke
parents:
diff changeset
5825 _edge_instructions.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
5826 _edge_instructions_idx.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
5827 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5828
a61af66fc99e Initial load
duke
parents:
diff changeset
5829 // append a lir-instruction-list and the index of the current operation in to the list
a61af66fc99e Initial load
duke
parents:
diff changeset
5830 void EdgeMoveOptimizer::append_instructions(LIR_OpList* instructions, int instructions_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5831 _edge_instructions.append(instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
5832 _edge_instructions_idx.append(instructions_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5833 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5834
a61af66fc99e Initial load
duke
parents:
diff changeset
5835 // return the current operation of the given edge (predecessor or successor)
a61af66fc99e Initial load
duke
parents:
diff changeset
5836 LIR_Op* EdgeMoveOptimizer::instruction_at(int edge) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5837 LIR_OpList* instructions = _edge_instructions.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5838 int idx = _edge_instructions_idx.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5839
a61af66fc99e Initial load
duke
parents:
diff changeset
5840 if (idx < instructions->length()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5841 return instructions->at(idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5842 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5843 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
5844 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5845 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5846
a61af66fc99e Initial load
duke
parents:
diff changeset
5847 // removes the current operation of the given edge (predecessor or successor)
a61af66fc99e Initial load
duke
parents:
diff changeset
5848 void EdgeMoveOptimizer::remove_cur_instruction(int edge, bool decrement_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5849 LIR_OpList* instructions = _edge_instructions.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5850 int idx = _edge_instructions_idx.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5851 instructions->remove_at(idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5852
a61af66fc99e Initial load
duke
parents:
diff changeset
5853 if (decrement_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5854 _edge_instructions_idx.at_put(edge, idx - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5855 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5856 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5857
a61af66fc99e Initial load
duke
parents:
diff changeset
5858
a61af66fc99e Initial load
duke
parents:
diff changeset
5859 bool EdgeMoveOptimizer::operations_different(LIR_Op* op1, LIR_Op* op2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5860 if (op1 == NULL || op2 == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5861 // at least one block is already empty -> no optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5862 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5863 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5864
a61af66fc99e Initial load
duke
parents:
diff changeset
5865 if (op1->code() == lir_move && op2->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5866 assert(op1->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5867 assert(op2->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5868 LIR_Op1* move1 = (LIR_Op1*)op1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5869 LIR_Op1* move2 = (LIR_Op1*)op2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5870 if (move1->info() == move2->info() && move1->in_opr() == move2->in_opr() && move1->result_opr() == move2->result_opr()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5871 // these moves are exactly equal and can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5872 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5873 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5874
a61af66fc99e Initial load
duke
parents:
diff changeset
5875 } else if (op1->code() == lir_fxch && op2->code() == lir_fxch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5876 assert(op1->as_Op1() != NULL, "fxch must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5877 assert(op2->as_Op1() != NULL, "fxch must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5878 LIR_Op1* fxch1 = (LIR_Op1*)op1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5879 LIR_Op1* fxch2 = (LIR_Op1*)op2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5880 if (fxch1->in_opr()->as_jint() == fxch2->in_opr()->as_jint()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5881 // equal FPU stack operations can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5882 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5883 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5884
a61af66fc99e Initial load
duke
parents:
diff changeset
5885 } else if (op1->code() == lir_fpop_raw && op2->code() == lir_fpop_raw) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5886 // equal FPU stack operations can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5887 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5888 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5889
a61af66fc99e Initial load
duke
parents:
diff changeset
5890 // no optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5891 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5892 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5893
a61af66fc99e Initial load
duke
parents:
diff changeset
5894 void EdgeMoveOptimizer::optimize_moves_at_block_end(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5895 TRACE_LINEAR_SCAN(4, tty->print_cr("optimizing moves at end of block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5896
a61af66fc99e Initial load
duke
parents:
diff changeset
5897 if (block->is_predecessor(block)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5898 // currently we can't handle this correctly.
a61af66fc99e Initial load
duke
parents:
diff changeset
5899 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5900 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5901
a61af66fc99e Initial load
duke
parents:
diff changeset
5902 init_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
5903 int num_preds = block->number_of_preds();
a61af66fc99e Initial load
duke
parents:
diff changeset
5904 assert(num_preds > 1, "do not call otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5905 assert(!block->is_set(BlockBegin::exception_entry_flag), "exception handlers not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
5906
a61af66fc99e Initial load
duke
parents:
diff changeset
5907 // setup a list with the lir-instructions of all predecessors
a61af66fc99e Initial load
duke
parents:
diff changeset
5908 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5909 for (i = 0; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5910 BlockBegin* pred = block->pred_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5911 LIR_OpList* pred_instructions = pred->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5912
a61af66fc99e Initial load
duke
parents:
diff changeset
5913 if (pred->number_of_sux() != 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5914 // this can happen with switch-statements where multiple edges are between
a61af66fc99e Initial load
duke
parents:
diff changeset
5915 // the same blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
5916 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5917 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5918
a61af66fc99e Initial load
duke
parents:
diff changeset
5919 assert(pred->number_of_sux() == 1, "can handle only one successor");
a61af66fc99e Initial load
duke
parents:
diff changeset
5920 assert(pred->sux_at(0) == block, "invalid control flow");
a61af66fc99e Initial load
duke
parents:
diff changeset
5921 assert(pred_instructions->last()->code() == lir_branch, "block with successor must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5922 assert(pred_instructions->last()->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5923 assert(pred_instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5924
a61af66fc99e Initial load
duke
parents:
diff changeset
5925 if (pred_instructions->last()->info() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5926 // can not optimize instructions when debug info is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5927 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5928 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5929
a61af66fc99e Initial load
duke
parents:
diff changeset
5930 // ignore the unconditional branch at the end of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
5931 append_instructions(pred_instructions, pred_instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5932 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5933
a61af66fc99e Initial load
duke
parents:
diff changeset
5934
a61af66fc99e Initial load
duke
parents:
diff changeset
5935 // process lir-instructions while all predecessors end with the same instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
5936 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5937 LIR_Op* op = instruction_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
5938 for (i = 1; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5939 if (operations_different(op, instruction_at(i))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5940 // these instructions are different and cannot be optimized ->
a61af66fc99e Initial load
duke
parents:
diff changeset
5941 // no further optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5942 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5943 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5944 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5945
a61af66fc99e Initial load
duke
parents:
diff changeset
5946 TRACE_LINEAR_SCAN(4, tty->print("found instruction that is equal in all %d predecessors: ", num_preds); op->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5947
a61af66fc99e Initial load
duke
parents:
diff changeset
5948 // insert the instruction at the beginning of the current block
a61af66fc99e Initial load
duke
parents:
diff changeset
5949 block->lir()->insert_before(1, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
5950
a61af66fc99e Initial load
duke
parents:
diff changeset
5951 // delete the instruction at the end of all predecessors
a61af66fc99e Initial load
duke
parents:
diff changeset
5952 for (i = 0; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5953 remove_cur_instruction(i, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5954 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5955 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5956 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5957
a61af66fc99e Initial load
duke
parents:
diff changeset
5958
a61af66fc99e Initial load
duke
parents:
diff changeset
5959 void EdgeMoveOptimizer::optimize_moves_at_block_begin(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5960 TRACE_LINEAR_SCAN(4, tty->print_cr("optimization moves at begin of block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5961
a61af66fc99e Initial load
duke
parents:
diff changeset
5962 init_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
5963 int num_sux = block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
5964
a61af66fc99e Initial load
duke
parents:
diff changeset
5965 LIR_OpList* cur_instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5966
a61af66fc99e Initial load
duke
parents:
diff changeset
5967 assert(num_sux == 2, "method should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5968 assert(cur_instructions->last()->code() == lir_branch, "block with successor must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5969 assert(cur_instructions->last()->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5970 assert(cur_instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5971
a61af66fc99e Initial load
duke
parents:
diff changeset
5972 if (cur_instructions->last()->info() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5973 // can no optimize instructions when debug info is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5974 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5975 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5976
a61af66fc99e Initial load
duke
parents:
diff changeset
5977 LIR_Op* branch = cur_instructions->at(cur_instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5978 if (branch->info() != NULL || (branch->code() != lir_branch && branch->code() != lir_cond_float_branch)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5979 // not a valid case for optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
5980 // currently, only blocks that end with two branches (conditional branch followed
a61af66fc99e Initial load
duke
parents:
diff changeset
5981 // by unconditional branch) are optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5982 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5983 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5984
a61af66fc99e Initial load
duke
parents:
diff changeset
5985 // now it is guaranteed that the block ends with two branch instructions.
a61af66fc99e Initial load
duke
parents:
diff changeset
5986 // the instructions are inserted at the end of the block before these two branches
a61af66fc99e Initial load
duke
parents:
diff changeset
5987 int insert_idx = cur_instructions->length() - 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5988
a61af66fc99e Initial load
duke
parents:
diff changeset
5989 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5990 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
5991 for (i = insert_idx - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5992 LIR_Op* op = cur_instructions->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5993 if ((op->code() == lir_branch || op->code() == lir_cond_float_branch) && ((LIR_OpBranch*)op)->block() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5994 assert(false, "block with two successors can have only two branch instructions");
a61af66fc99e Initial load
duke
parents:
diff changeset
5995 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5996 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5997 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5998
a61af66fc99e Initial load
duke
parents:
diff changeset
5999 // setup a list with the lir-instructions of all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
6000 for (i = 0; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6001 BlockBegin* sux = block->sux_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6002 LIR_OpList* sux_instructions = sux->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6003
a61af66fc99e Initial load
duke
parents:
diff changeset
6004 assert(sux_instructions->at(0)->code() == lir_label, "block must start with label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6005
a61af66fc99e Initial load
duke
parents:
diff changeset
6006 if (sux->number_of_preds() != 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6007 // this can happen with switch-statements where multiple edges are between
a61af66fc99e Initial load
duke
parents:
diff changeset
6008 // the same blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
6009 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
6010 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6011 assert(sux->pred_at(0) == block, "invalid control flow");
a61af66fc99e Initial load
duke
parents:
diff changeset
6012 assert(!sux->is_set(BlockBegin::exception_entry_flag), "exception handlers not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
6013
a61af66fc99e Initial load
duke
parents:
diff changeset
6014 // ignore the label at the beginning of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
6015 append_instructions(sux_instructions, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
6016 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6017
a61af66fc99e Initial load
duke
parents:
diff changeset
6018 // process lir-instructions while all successors begin with the same instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6019 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6020 LIR_Op* op = instruction_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
6021 for (i = 1; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6022 if (operations_different(op, instruction_at(i))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6023 // these instructions are different and cannot be optimized ->
a61af66fc99e Initial load
duke
parents:
diff changeset
6024 // no further optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
6025 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
6026 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6027 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6028
a61af66fc99e Initial load
duke
parents:
diff changeset
6029 TRACE_LINEAR_SCAN(4, tty->print("----- found instruction that is equal in all %d successors: ", num_sux); op->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
6030
a61af66fc99e Initial load
duke
parents:
diff changeset
6031 // insert instruction at end of current block
a61af66fc99e Initial load
duke
parents:
diff changeset
6032 block->lir()->insert_before(insert_idx, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
6033 insert_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6034
a61af66fc99e Initial load
duke
parents:
diff changeset
6035 // delete the instructions at the beginning of all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
6036 for (i = 0; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6037 remove_cur_instruction(i, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
6038 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6039 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6040 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6041
a61af66fc99e Initial load
duke
parents:
diff changeset
6042
a61af66fc99e Initial load
duke
parents:
diff changeset
6043 // Implementation of ControlFlowOptimizer
a61af66fc99e Initial load
duke
parents:
diff changeset
6044
a61af66fc99e Initial load
duke
parents:
diff changeset
6045 ControlFlowOptimizer::ControlFlowOptimizer() :
a61af66fc99e Initial load
duke
parents:
diff changeset
6046 _original_preds(4)
a61af66fc99e Initial load
duke
parents:
diff changeset
6047 {
a61af66fc99e Initial load
duke
parents:
diff changeset
6048 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6049
a61af66fc99e Initial load
duke
parents:
diff changeset
6050 void ControlFlowOptimizer::optimize(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6051 ControlFlowOptimizer optimizer = ControlFlowOptimizer();
a61af66fc99e Initial load
duke
parents:
diff changeset
6052
a61af66fc99e Initial load
duke
parents:
diff changeset
6053 // push the OSR entry block to the end so that we're not jumping over it.
a61af66fc99e Initial load
duke
parents:
diff changeset
6054 BlockBegin* osr_entry = code->at(0)->end()->as_Base()->osr_entry();
a61af66fc99e Initial load
duke
parents:
diff changeset
6055 if (osr_entry) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6056 int index = osr_entry->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
6057 assert(code->at(index) == osr_entry, "wrong index");
a61af66fc99e Initial load
duke
parents:
diff changeset
6058 code->remove_at(index);
a61af66fc99e Initial load
duke
parents:
diff changeset
6059 code->append(osr_entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
6060 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6061
a61af66fc99e Initial load
duke
parents:
diff changeset
6062 optimizer.reorder_short_loops(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6063 optimizer.delete_empty_blocks(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6064 optimizer.delete_unnecessary_jumps(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6065 optimizer.delete_jumps_to_return(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6066 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6067
a61af66fc99e Initial load
duke
parents:
diff changeset
6068 void ControlFlowOptimizer::reorder_short_loop(BlockList* code, BlockBegin* header_block, int header_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6069 int i = header_idx + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6070 int max_end = MIN2(header_idx + ShortLoopSize, code->length());
a61af66fc99e Initial load
duke
parents:
diff changeset
6071 while (i < max_end && code->at(i)->loop_depth() >= header_block->loop_depth()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6072 i++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6073 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6074
a61af66fc99e Initial load
duke
parents:
diff changeset
6075 if (i == code->length() || code->at(i)->loop_depth() < header_block->loop_depth()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6076 int end_idx = i - 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6077 BlockBegin* end_block = code->at(end_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
6078
a61af66fc99e Initial load
duke
parents:
diff changeset
6079 if (end_block->number_of_sux() == 1 && end_block->sux_at(0) == header_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6080 // short loop from header_idx to end_idx found -> reorder blocks such that
a61af66fc99e Initial load
duke
parents:
diff changeset
6081 // the header_block is the last block instead of the first block of the loop
a61af66fc99e Initial load
duke
parents:
diff changeset
6082 TRACE_LINEAR_SCAN(1, tty->print_cr("Reordering short loop: length %d, header B%d, end B%d",
a61af66fc99e Initial load
duke
parents:
diff changeset
6083 end_idx - header_idx + 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
6084 header_block->block_id(), end_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
6085
a61af66fc99e Initial load
duke
parents:
diff changeset
6086 for (int j = header_idx; j < end_idx; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6087 code->at_put(j, code->at(j + 1));
a61af66fc99e Initial load
duke
parents:
diff changeset
6088 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6089 code->at_put(end_idx, header_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6090
a61af66fc99e Initial load
duke
parents:
diff changeset
6091 // correct the flags so that any loop alignment occurs in the right place.
a61af66fc99e Initial load
duke
parents:
diff changeset
6092 assert(code->at(end_idx)->is_set(BlockBegin::backward_branch_target_flag), "must be backward branch target");
a61af66fc99e Initial load
duke
parents:
diff changeset
6093 code->at(end_idx)->clear(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6094 code->at(header_idx)->set(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6095 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6096 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6097 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6098
a61af66fc99e Initial load
duke
parents:
diff changeset
6099 void ControlFlowOptimizer::reorder_short_loops(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6100 for (int i = code->length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6101 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6102
a61af66fc99e Initial load
duke
parents:
diff changeset
6103 if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6104 reorder_short_loop(code, block, i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6105 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6106 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6107
a61af66fc99e Initial load
duke
parents:
diff changeset
6108 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6109 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6110
a61af66fc99e Initial load
duke
parents:
diff changeset
6111 // only blocks with exactly one successor can be deleted. Such blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
6112 // must always end with an unconditional branch to this successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6113 bool ControlFlowOptimizer::can_delete_block(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6114 if (block->number_of_sux() != 1 || block->number_of_exception_handlers() != 0 || block->is_entry_block()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6115 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6116 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6117
a61af66fc99e Initial load
duke
parents:
diff changeset
6118 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6119
a61af66fc99e Initial load
duke
parents:
diff changeset
6120 assert(instructions->length() >= 2, "block must have label and branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6121 assert(instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6122 assert(instructions->last()->as_OpBranch() != NULL, "last instrcution must always be a branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6123 assert(instructions->last()->as_OpBranch()->cond() == lir_cond_always, "branch must be unconditional");
a61af66fc99e Initial load
duke
parents:
diff changeset
6124 assert(instructions->last()->as_OpBranch()->block() == block->sux_at(0), "branch target must be the successor");
a61af66fc99e Initial load
duke
parents:
diff changeset
6125
a61af66fc99e Initial load
duke
parents:
diff changeset
6126 // block must have exactly one successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6127
a61af66fc99e Initial load
duke
parents:
diff changeset
6128 if (instructions->length() == 2 && instructions->last()->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6129 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
6130 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6131 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6132 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6133
a61af66fc99e Initial load
duke
parents:
diff changeset
6134 // substitute branch targets in all branch-instructions of this blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
6135 void ControlFlowOptimizer::substitute_branch_target(BlockBegin* block, BlockBegin* target_from, BlockBegin* target_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6136 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()));
a61af66fc99e Initial load
duke
parents:
diff changeset
6137
a61af66fc99e Initial load
duke
parents:
diff changeset
6138 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6139
a61af66fc99e Initial load
duke
parents:
diff changeset
6140 assert(instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6141 for (int i = instructions->length() - 1; i >= 1; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6142 LIR_Op* op = instructions->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6143
a61af66fc99e Initial load
duke
parents:
diff changeset
6144 if (op->code() == lir_branch || op->code() == lir_cond_float_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6145 assert(op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6146 LIR_OpBranch* branch = (LIR_OpBranch*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6147
a61af66fc99e Initial load
duke
parents:
diff changeset
6148 if (branch->block() == target_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6149 branch->change_block(target_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
6150 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6151 if (branch->ublock() == target_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6152 branch->change_ublock(target_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
6153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6154 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6155 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6157
a61af66fc99e Initial load
duke
parents:
diff changeset
6158 void ControlFlowOptimizer::delete_empty_blocks(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6159 int old_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6160 int new_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6161 int num_blocks = code->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
6162
a61af66fc99e Initial load
duke
parents:
diff changeset
6163 while (old_pos < num_blocks) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6164 BlockBegin* block = code->at(old_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
6165
a61af66fc99e Initial load
duke
parents:
diff changeset
6166 if (can_delete_block(block)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6167 BlockBegin* new_target = block->sux_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
6168
a61af66fc99e Initial load
duke
parents:
diff changeset
6169 // propagate backward branch target flag for correct code alignment
a61af66fc99e Initial load
duke
parents:
diff changeset
6170 if (block->is_set(BlockBegin::backward_branch_target_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6171 new_target->set(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6172 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6173
a61af66fc99e Initial load
duke
parents:
diff changeset
6174 // collect a list with all predecessors that contains each predecessor only once
a61af66fc99e Initial load
duke
parents:
diff changeset
6175 // the predecessors of cur are changed during the substitution, so a copy of the
a61af66fc99e Initial load
duke
parents:
diff changeset
6176 // predecessor list is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
6177 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
6178 _original_preds.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
6179 for (j = block->number_of_preds() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6180 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6181 if (_original_preds.index_of(pred) == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6182 _original_preds.append(pred);
a61af66fc99e Initial load
duke
parents:
diff changeset
6183 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6184 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6185
a61af66fc99e Initial load
duke
parents:
diff changeset
6186 for (j = _original_preds.length() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6187 BlockBegin* pred = _original_preds.at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6188 substitute_branch_target(pred, block, new_target);
a61af66fc99e Initial load
duke
parents:
diff changeset
6189 pred->substitute_sux(block, new_target);
a61af66fc99e Initial load
duke
parents:
diff changeset
6190 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6191 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6192 // adjust position of this block in the block list if blocks before
a61af66fc99e Initial load
duke
parents:
diff changeset
6193 // have been deleted
a61af66fc99e Initial load
duke
parents:
diff changeset
6194 if (new_pos != old_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6195 code->at_put(new_pos, code->at(old_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
6196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6197 new_pos++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6198 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6199 old_pos++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6201 code->truncate(new_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
6202
a61af66fc99e Initial load
duke
parents:
diff changeset
6203 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6204 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6205
a61af66fc99e Initial load
duke
parents:
diff changeset
6206 void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6207 // skip the last block because there a branch is always necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
6208 for (int i = code->length() - 2; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6209 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6210 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6211
a61af66fc99e Initial load
duke
parents:
diff changeset
6212 LIR_Op* last_op = instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6213 if (last_op->code() == lir_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6214 assert(last_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6215 LIR_OpBranch* last_branch = (LIR_OpBranch*)last_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6216
a61af66fc99e Initial load
duke
parents:
diff changeset
6217 assert(last_branch->block() != NULL, "last branch must always have a block as target");
a61af66fc99e Initial load
duke
parents:
diff changeset
6218 assert(last_branch->label() == last_branch->block()->label(), "must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
6219
a61af66fc99e Initial load
duke
parents:
diff changeset
6220 if (last_branch->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6221 if (last_branch->block() == code->at(i + 1)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6222
a61af66fc99e Initial load
duke
parents:
diff changeset
6223 TRACE_LINEAR_SCAN(3, tty->print_cr("Deleting unconditional branch at end of block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
6224
a61af66fc99e Initial load
duke
parents:
diff changeset
6225 // delete last branch instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6226 instructions->truncate(instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
6227
a61af66fc99e Initial load
duke
parents:
diff changeset
6228 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6229 LIR_Op* prev_op = instructions->at(instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
6230 if (prev_op->code() == lir_branch || prev_op->code() == lir_cond_float_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6231 assert(prev_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6232 LIR_OpBranch* prev_branch = (LIR_OpBranch*)prev_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6233
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6234 LIR_Op2* prev_cmp = NULL;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6235
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6236 for(int j = instructions->length() - 3; j >= 0 && prev_cmp == NULL; j--) {
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6237 prev_op = instructions->at(j);
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6238 if(prev_op->code() == lir_cmp) {
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6239 assert(prev_op->as_Op2() != NULL, "branch must be of type LIR_Op2");
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6240 prev_cmp = (LIR_Op2*)prev_op;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6241 assert(prev_branch->cond() == prev_cmp->condition(), "should be the same");
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6242 }
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6243 }
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6244 assert(prev_cmp != NULL, "should have found comp instruction for branch");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
6245 if (prev_branch->block() == code->at(i + 1) && prev_branch->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6246
a61af66fc99e Initial load
duke
parents:
diff changeset
6247 TRACE_LINEAR_SCAN(3, tty->print_cr("Negating conditional branch and deleting unconditional branch at end of block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
6248
a61af66fc99e Initial load
duke
parents:
diff changeset
6249 // eliminate a conditional branch to the immediate successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6250 prev_branch->change_block(last_branch->block());
a61af66fc99e Initial load
duke
parents:
diff changeset
6251 prev_branch->negate_cond();
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6252 prev_cmp->set_condition(prev_branch->cond());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
6253 instructions->truncate(instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
6254 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6255 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6256 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6258 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6259 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6260
a61af66fc99e Initial load
duke
parents:
diff changeset
6261 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6262 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6263
a61af66fc99e Initial load
duke
parents:
diff changeset
6264 void ControlFlowOptimizer::delete_jumps_to_return(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6265 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6266 BitMap return_converted(BlockBegin::number_of_blocks());
a61af66fc99e Initial load
duke
parents:
diff changeset
6267 return_converted.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
6268 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6269
a61af66fc99e Initial load
duke
parents:
diff changeset
6270 for (int i = code->length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6271 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6272 LIR_OpList* cur_instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6273 LIR_Op* cur_last_op = cur_instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6274
a61af66fc99e Initial load
duke
parents:
diff changeset
6275 assert(cur_instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6276 if (cur_instructions->length() == 2 && cur_last_op->code() == lir_return) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6277 // the block contains only a label and a return
a61af66fc99e Initial load
duke
parents:
diff changeset
6278 // if a predecessor ends with an unconditional jump to this block, then the jump
a61af66fc99e Initial load
duke
parents:
diff changeset
6279 // can be replaced with a return instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6280 //
a61af66fc99e Initial load
duke
parents:
diff changeset
6281 // Note: the original block with only a return statement cannot be deleted completely
a61af66fc99e Initial load
duke
parents:
diff changeset
6282 // because the predecessors might have other (conditional) jumps to this block
a61af66fc99e Initial load
duke
parents:
diff changeset
6283 // -> this may lead to unnecesary return instructions in the final code
a61af66fc99e Initial load
duke
parents:
diff changeset
6284
a61af66fc99e Initial load
duke
parents:
diff changeset
6285 assert(cur_last_op->info() == NULL, "return instructions do not have debug information");
a61af66fc99e Initial load
duke
parents:
diff changeset
6286 assert(block->number_of_sux() == 0 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
6287 (return_converted.at(block->block_id()) && block->number_of_sux() == 1),
a61af66fc99e Initial load
duke
parents:
diff changeset
6288 "blocks that end with return must not have successors");
a61af66fc99e Initial load
duke
parents:
diff changeset
6289
a61af66fc99e Initial load
duke
parents:
diff changeset
6290 assert(cur_last_op->as_Op1() != NULL, "return must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
6291 LIR_Opr return_opr = ((LIR_Op1*)cur_last_op)->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6292
a61af66fc99e Initial load
duke
parents:
diff changeset
6293 for (int j = block->number_of_preds() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6294 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6295 LIR_OpList* pred_instructions = pred->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6296 LIR_Op* pred_last_op = pred_instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6297
a61af66fc99e Initial load
duke
parents:
diff changeset
6298 if (pred_last_op->code() == lir_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6299 assert(pred_last_op->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6300 LIR_OpBranch* pred_last_branch = (LIR_OpBranch*)pred_last_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6301
a61af66fc99e Initial load
duke
parents:
diff changeset
6302 if (pred_last_branch->block() == block && pred_last_branch->cond() == lir_cond_always && pred_last_branch->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6303 // replace the jump to a return with a direct return
a61af66fc99e Initial load
duke
parents:
diff changeset
6304 // Note: currently the edge between the blocks is not deleted
a61af66fc99e Initial load
duke
parents:
diff changeset
6305 pred_instructions->at_put(pred_instructions->length() - 1, new LIR_Op1(lir_return, return_opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
6306 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6307 return_converted.set_bit(pred->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
6308 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6309 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6310 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6311 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6312 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6313 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6314 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6315
a61af66fc99e Initial load
duke
parents:
diff changeset
6316
a61af66fc99e Initial load
duke
parents:
diff changeset
6317 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6318 void ControlFlowOptimizer::verify(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6319 for (int i = 0; i < code->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6320 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6321 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6322
a61af66fc99e Initial load
duke
parents:
diff changeset
6323 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
6324 for (j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6325 LIR_OpBranch* op_branch = instructions->at(j)->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
6326
a61af66fc99e Initial load
duke
parents:
diff changeset
6327 if (op_branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6328 assert(op_branch->block() == NULL || code->index_of(op_branch->block()) != -1, "branch target not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6329 assert(op_branch->ublock() == NULL || code->index_of(op_branch->ublock()) != -1, "branch target not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6330 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6331 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6332
a61af66fc99e Initial load
duke
parents:
diff changeset
6333 for (j = 0; j < block->number_of_sux() - 1; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6334 BlockBegin* sux = block->sux_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6335 assert(code->index_of(sux) != -1, "successor not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6336 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6337
a61af66fc99e Initial load
duke
parents:
diff changeset
6338 for (j = 0; j < block->number_of_preds() - 1; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6339 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6340 assert(code->index_of(pred) != -1, "successor not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6341 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6342 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6343 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6344 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6345
a61af66fc99e Initial load
duke
parents:
diff changeset
6346
a61af66fc99e Initial load
duke
parents:
diff changeset
6347 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
6348
a61af66fc99e Initial load
duke
parents:
diff changeset
6349 // Implementation of LinearStatistic
a61af66fc99e Initial load
duke
parents:
diff changeset
6350
a61af66fc99e Initial load
duke
parents:
diff changeset
6351 const char* LinearScanStatistic::counter_name(int counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6352 switch (counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6353 case counter_method: return "compiled methods";
a61af66fc99e Initial load
duke
parents:
diff changeset
6354 case counter_fpu_method: return "methods using fpu";
a61af66fc99e Initial load
duke
parents:
diff changeset
6355 case counter_loop_method: return "methods with loops";
a61af66fc99e Initial load
duke
parents:
diff changeset
6356 case counter_exception_method:return "methods with xhandler";
a61af66fc99e Initial load
duke
parents:
diff changeset
6357
a61af66fc99e Initial load
duke
parents:
diff changeset
6358 case counter_loop: return "loops";
a61af66fc99e Initial load
duke
parents:
diff changeset
6359 case counter_block: return "blocks";
a61af66fc99e Initial load
duke
parents:
diff changeset
6360 case counter_loop_block: return "blocks inside loop";
a61af66fc99e Initial load
duke
parents:
diff changeset
6361 case counter_exception_block: return "exception handler entries";
a61af66fc99e Initial load
duke
parents:
diff changeset
6362 case counter_interval: return "intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6363 case counter_fixed_interval: return "fixed intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6364 case counter_range: return "ranges";
a61af66fc99e Initial load
duke
parents:
diff changeset
6365 case counter_fixed_range: return "fixed ranges";
a61af66fc99e Initial load
duke
parents:
diff changeset
6366 case counter_use_pos: return "use positions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6367 case counter_fixed_use_pos: return "fixed use positions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6368 case counter_spill_slots: return "spill slots";
a61af66fc99e Initial load
duke
parents:
diff changeset
6369
a61af66fc99e Initial load
duke
parents:
diff changeset
6370 // counter for classes of lir instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
6371 case counter_instruction: return "total instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6372 case counter_label: return "labels";
a61af66fc99e Initial load
duke
parents:
diff changeset
6373 case counter_entry: return "method entries";
a61af66fc99e Initial load
duke
parents:
diff changeset
6374 case counter_return: return "method returns";
a61af66fc99e Initial load
duke
parents:
diff changeset
6375 case counter_call: return "method calls";
a61af66fc99e Initial load
duke
parents:
diff changeset
6376 case counter_move: return "moves";
a61af66fc99e Initial load
duke
parents:
diff changeset
6377 case counter_cmp: return "compare";
a61af66fc99e Initial load
duke
parents:
diff changeset
6378 case counter_cond_branch: return "conditional branches";
a61af66fc99e Initial load
duke
parents:
diff changeset
6379 case counter_uncond_branch: return "unconditional branches";
a61af66fc99e Initial load
duke
parents:
diff changeset
6380 case counter_stub_branch: return "branches to stub";
a61af66fc99e Initial load
duke
parents:
diff changeset
6381 case counter_alu: return "artithmetic + logic";
a61af66fc99e Initial load
duke
parents:
diff changeset
6382 case counter_alloc: return "allocations";
a61af66fc99e Initial load
duke
parents:
diff changeset
6383 case counter_sync: return "synchronisation";
a61af66fc99e Initial load
duke
parents:
diff changeset
6384 case counter_throw: return "throw";
a61af66fc99e Initial load
duke
parents:
diff changeset
6385 case counter_unwind: return "unwind";
a61af66fc99e Initial load
duke
parents:
diff changeset
6386 case counter_typecheck: return "type+null-checks";
a61af66fc99e Initial load
duke
parents:
diff changeset
6387 case counter_fpu_stack: return "fpu-stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6388 case counter_misc_inst: return "other instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6389 case counter_other_inst: return "misc. instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6390
a61af66fc99e Initial load
duke
parents:
diff changeset
6391 // counter for different types of moves
a61af66fc99e Initial load
duke
parents:
diff changeset
6392 case counter_move_total: return "total moves";
a61af66fc99e Initial load
duke
parents:
diff changeset
6393 case counter_move_reg_reg: return "register->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6394 case counter_move_reg_stack: return "register->stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6395 case counter_move_stack_reg: return "stack->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6396 case counter_move_stack_stack:return "stack->stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6397 case counter_move_reg_mem: return "register->memory";
a61af66fc99e Initial load
duke
parents:
diff changeset
6398 case counter_move_mem_reg: return "memory->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6399 case counter_move_const_any: return "constant->any";
a61af66fc99e Initial load
duke
parents:
diff changeset
6400
a61af66fc99e Initial load
duke
parents:
diff changeset
6401 case blank_line_1: return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6402 case blank_line_2: return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6403
a61af66fc99e Initial load
duke
parents:
diff changeset
6404 default: ShouldNotReachHere(); return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6405 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6406 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6407
a61af66fc99e Initial load
duke
parents:
diff changeset
6408 LinearScanStatistic::Counter LinearScanStatistic::base_counter(int counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6409 if (counter_idx == counter_fpu_method || counter_idx == counter_loop_method || counter_idx == counter_exception_method) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6410 return counter_method;
a61af66fc99e Initial load
duke
parents:
diff changeset
6411 } else if (counter_idx == counter_loop_block || counter_idx == counter_exception_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6412 return counter_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
6413 } else if (counter_idx >= counter_instruction && counter_idx <= counter_other_inst) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6414 return counter_instruction;
a61af66fc99e Initial load
duke
parents:
diff changeset
6415 } else if (counter_idx >= counter_move_total && counter_idx <= counter_move_const_any) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6416 return counter_move_total;
a61af66fc99e Initial load
duke
parents:
diff changeset
6417 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6418 return invalid_counter;
a61af66fc99e Initial load
duke
parents:
diff changeset
6419 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6420
a61af66fc99e Initial load
duke
parents:
diff changeset
6421 LinearScanStatistic::LinearScanStatistic() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6422 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6423 _counters_sum[i] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6424 _counters_max[i] = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6425 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6426
a61af66fc99e Initial load
duke
parents:
diff changeset
6427 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6428
a61af66fc99e Initial load
duke
parents:
diff changeset
6429 // add the method-local numbers to the total sum
a61af66fc99e Initial load
duke
parents:
diff changeset
6430 void LinearScanStatistic::sum_up(LinearScanStatistic &method_statistic) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6431 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6432 _counters_sum[i] += method_statistic._counters_sum[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
6433 _counters_max[i] = MAX2(_counters_max[i], method_statistic._counters_sum[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6434 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6435 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6436
a61af66fc99e Initial load
duke
parents:
diff changeset
6437 void LinearScanStatistic::print(const char* title) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6438 if (CountLinearScan || TraceLinearScanLevel > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6439 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6440 tty->print_cr("***** LinearScan statistic - %s *****", title);
a61af66fc99e Initial load
duke
parents:
diff changeset
6441
a61af66fc99e Initial load
duke
parents:
diff changeset
6442 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6443 if (_counters_sum[i] > 0 || _counters_max[i] >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6444 tty->print("%25s: %8d", counter_name(i), _counters_sum[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6445
a61af66fc99e Initial load
duke
parents:
diff changeset
6446 if (base_counter(i) != invalid_counter) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6447 tty->print(" (%5.1f%%) ", _counters_sum[i] * 100.0 / _counters_sum[base_counter(i)]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6448 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6449 tty->print(" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
6450 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6451
a61af66fc99e Initial load
duke
parents:
diff changeset
6452 if (_counters_max[i] >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6453 tty->print("%8d", _counters_max[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6454 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6455 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6456 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6457 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6458 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6459 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6460
a61af66fc99e Initial load
duke
parents:
diff changeset
6461 void LinearScanStatistic::collect(LinearScan* allocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6462 inc_counter(counter_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6463 if (allocator->has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6464 inc_counter(counter_fpu_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6465 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6466 if (allocator->num_loops() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6467 inc_counter(counter_loop_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6468 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6469 inc_counter(counter_loop, allocator->num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
6470 inc_counter(counter_spill_slots, allocator->max_spills());
a61af66fc99e Initial load
duke
parents:
diff changeset
6471
a61af66fc99e Initial load
duke
parents:
diff changeset
6472 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
6473 for (i = 0; i < allocator->interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6474 Interval* cur = allocator->interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6475
a61af66fc99e Initial load
duke
parents:
diff changeset
6476 if (cur != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6477 inc_counter(counter_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
6478 inc_counter(counter_use_pos, cur->num_use_positions());
a61af66fc99e Initial load
duke
parents:
diff changeset
6479 if (LinearScan::is_precolored_interval(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6480 inc_counter(counter_fixed_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
6481 inc_counter(counter_fixed_use_pos, cur->num_use_positions());
a61af66fc99e Initial load
duke
parents:
diff changeset
6482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6483
a61af66fc99e Initial load
duke
parents:
diff changeset
6484 Range* range = cur->first();
a61af66fc99e Initial load
duke
parents:
diff changeset
6485 while (range != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6486 inc_counter(counter_range);
a61af66fc99e Initial load
duke
parents:
diff changeset
6487 if (LinearScan::is_precolored_interval(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6488 inc_counter(counter_fixed_range);
a61af66fc99e Initial load
duke
parents:
diff changeset
6489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6490 range = range->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
6491 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6492 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6493 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6494
a61af66fc99e Initial load
duke
parents:
diff changeset
6495 bool has_xhandlers = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6496 // Note: only count blocks that are in code-emit order
a61af66fc99e Initial load
duke
parents:
diff changeset
6497 for (i = 0; i < allocator->ir()->code()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6498 BlockBegin* cur = allocator->ir()->code()->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6499
a61af66fc99e Initial load
duke
parents:
diff changeset
6500 inc_counter(counter_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6501 if (cur->loop_depth() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6502 inc_counter(counter_loop_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6503 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6504 if (cur->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6505 inc_counter(counter_exception_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6506 has_xhandlers = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
6507 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6508
a61af66fc99e Initial load
duke
parents:
diff changeset
6509 LIR_OpList* instructions = cur->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6510 for (int j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6511 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6512
a61af66fc99e Initial load
duke
parents:
diff changeset
6513 inc_counter(counter_instruction);
a61af66fc99e Initial load
duke
parents:
diff changeset
6514
a61af66fc99e Initial load
duke
parents:
diff changeset
6515 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6516 case lir_label: inc_counter(counter_label); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6517 case lir_std_entry:
a61af66fc99e Initial load
duke
parents:
diff changeset
6518 case lir_osr_entry: inc_counter(counter_entry); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6519 case lir_return: inc_counter(counter_return); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6520
a61af66fc99e Initial load
duke
parents:
diff changeset
6521 case lir_rtcall:
a61af66fc99e Initial load
duke
parents:
diff changeset
6522 case lir_static_call:
a61af66fc99e Initial load
duke
parents:
diff changeset
6523 case lir_optvirtual_call:
a61af66fc99e Initial load
duke
parents:
diff changeset
6524 case lir_virtual_call: inc_counter(counter_call); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6525
a61af66fc99e Initial load
duke
parents:
diff changeset
6526 case lir_move: {
a61af66fc99e Initial load
duke
parents:
diff changeset
6527 inc_counter(counter_move);
a61af66fc99e Initial load
duke
parents:
diff changeset
6528 inc_counter(counter_move_total);
a61af66fc99e Initial load
duke
parents:
diff changeset
6529
a61af66fc99e Initial load
duke
parents:
diff changeset
6530 LIR_Opr in = op->as_Op1()->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6531 LIR_Opr res = op->as_Op1()->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6532 if (in->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6533 if (res->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6534 inc_counter(counter_move_reg_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6535 } else if (res->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6536 inc_counter(counter_move_reg_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
6537 } else if (res->is_address()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6538 inc_counter(counter_move_reg_mem);
a61af66fc99e Initial load
duke
parents:
diff changeset
6539 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6540 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
6541 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6542 } else if (in->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6543 if (res->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6544 inc_counter(counter_move_stack_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6545 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6546 inc_counter(counter_move_stack_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
6547 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6548 } else if (in->is_address()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6549 assert(res->is_register(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
6550 inc_counter(counter_move_mem_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6551 } else if (in->is_constant()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6552 inc_counter(counter_move_const_any);
a61af66fc99e Initial load
duke
parents:
diff changeset
6553 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6554 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
6555 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6556 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6557 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6558
a61af66fc99e Initial load
duke
parents:
diff changeset
6559 case lir_cmp: inc_counter(counter_cmp); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6560
a61af66fc99e Initial load
duke
parents:
diff changeset
6561 case lir_branch:
a61af66fc99e Initial load
duke
parents:
diff changeset
6562 case lir_cond_float_branch: {
a61af66fc99e Initial load
duke
parents:
diff changeset
6563 LIR_OpBranch* branch = op->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
6564 if (branch->block() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6565 inc_counter(counter_stub_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6566 } else if (branch->cond() == lir_cond_always) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6567 inc_counter(counter_uncond_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6568 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6569 inc_counter(counter_cond_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6571 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6572 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6573
a61af66fc99e Initial load
duke
parents:
diff changeset
6574 case lir_neg:
a61af66fc99e Initial load
duke
parents:
diff changeset
6575 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
6576 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
6577 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
6578 case lir_mul_strictfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6579 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
6580 case lir_div_strictfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6581 case lir_rem:
a61af66fc99e Initial load
duke
parents:
diff changeset
6582 case lir_sqrt:
a61af66fc99e Initial load
duke
parents:
diff changeset
6583 case lir_sin:
a61af66fc99e Initial load
duke
parents:
diff changeset
6584 case lir_cos:
a61af66fc99e Initial load
duke
parents:
diff changeset
6585 case lir_abs:
a61af66fc99e Initial load
duke
parents:
diff changeset
6586 case lir_log10:
a61af66fc99e Initial load
duke
parents:
diff changeset
6587 case lir_log:
6084
6759698e3140 7133857: exp() and pow() should use the x87 ISA on x86
roland
parents: 5906
diff changeset
6588 case lir_pow:
6759698e3140 7133857: exp() and pow() should use the x87 ISA on x86
roland
parents: 5906
diff changeset
6589 case lir_exp:
0
a61af66fc99e Initial load
duke
parents:
diff changeset
6590 case lir_logic_and:
a61af66fc99e Initial load
duke
parents:
diff changeset
6591 case lir_logic_or:
a61af66fc99e Initial load
duke
parents:
diff changeset
6592 case lir_logic_xor:
a61af66fc99e Initial load
duke
parents:
diff changeset
6593 case lir_shl:
a61af66fc99e Initial load
duke
parents:
diff changeset
6594 case lir_shr:
a61af66fc99e Initial load
duke
parents:
diff changeset
6595 case lir_ushr: inc_counter(counter_alu); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6596
a61af66fc99e Initial load
duke
parents:
diff changeset
6597 case lir_alloc_object:
a61af66fc99e Initial load
duke
parents:
diff changeset
6598 case lir_alloc_array: inc_counter(counter_alloc); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6599
a61af66fc99e Initial load
duke
parents:
diff changeset
6600 case lir_monaddr:
a61af66fc99e Initial load
duke
parents:
diff changeset
6601 case lir_lock:
a61af66fc99e Initial load
duke
parents:
diff changeset
6602 case lir_unlock: inc_counter(counter_sync); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6603
a61af66fc99e Initial load
duke
parents:
diff changeset
6604 case lir_throw: inc_counter(counter_throw); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6605
a61af66fc99e Initial load
duke
parents:
diff changeset
6606 case lir_unwind: inc_counter(counter_unwind); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6607
a61af66fc99e Initial load
duke
parents:
diff changeset
6608 case lir_null_check:
a61af66fc99e Initial load
duke
parents:
diff changeset
6609 case lir_leal:
a61af66fc99e Initial load
duke
parents:
diff changeset
6610 case lir_instanceof:
a61af66fc99e Initial load
duke
parents:
diff changeset
6611 case lir_checkcast:
a61af66fc99e Initial load
duke
parents:
diff changeset
6612 case lir_store_check: inc_counter(counter_typecheck); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6613
a61af66fc99e Initial load
duke
parents:
diff changeset
6614 case lir_fpop_raw:
a61af66fc99e Initial load
duke
parents:
diff changeset
6615 case lir_fxch:
a61af66fc99e Initial load
duke
parents:
diff changeset
6616 case lir_fld: inc_counter(counter_fpu_stack); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6617
a61af66fc99e Initial load
duke
parents:
diff changeset
6618 case lir_nop:
a61af66fc99e Initial load
duke
parents:
diff changeset
6619 case lir_push:
a61af66fc99e Initial load
duke
parents:
diff changeset
6620 case lir_pop:
a61af66fc99e Initial load
duke
parents:
diff changeset
6621 case lir_convert:
a61af66fc99e Initial load
duke
parents:
diff changeset
6622 case lir_roundfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6623 case lir_cmove: inc_counter(counter_misc_inst); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6624
a61af66fc99e Initial load
duke
parents:
diff changeset
6625 default: inc_counter(counter_other_inst); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6626 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6627 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6628 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6629
a61af66fc99e Initial load
duke
parents:
diff changeset
6630 if (has_xhandlers) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6631 inc_counter(counter_exception_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6632 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6633 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6634
a61af66fc99e Initial load
duke
parents:
diff changeset
6635 void LinearScanStatistic::compute(LinearScan* allocator, LinearScanStatistic &global_statistic) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6636 if (CountLinearScan || TraceLinearScanLevel > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6637
a61af66fc99e Initial load
duke
parents:
diff changeset
6638 LinearScanStatistic local_statistic = LinearScanStatistic();
a61af66fc99e Initial load
duke
parents:
diff changeset
6639
a61af66fc99e Initial load
duke
parents:
diff changeset
6640 local_statistic.collect(allocator);
a61af66fc99e Initial load
duke
parents:
diff changeset
6641 global_statistic.sum_up(local_statistic);
a61af66fc99e Initial load
duke
parents:
diff changeset
6642
a61af66fc99e Initial load
duke
parents:
diff changeset
6643 if (TraceLinearScanLevel > 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6644 local_statistic.print("current local statistic");
a61af66fc99e Initial load
duke
parents:
diff changeset
6645 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6646 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6647 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6648
a61af66fc99e Initial load
duke
parents:
diff changeset
6649
a61af66fc99e Initial load
duke
parents:
diff changeset
6650 // Implementation of LinearTimers
a61af66fc99e Initial load
duke
parents:
diff changeset
6651
a61af66fc99e Initial load
duke
parents:
diff changeset
6652 LinearScanTimers::LinearScanTimers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6653 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6654 timer(i)->reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
6655 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6656 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6657
a61af66fc99e Initial load
duke
parents:
diff changeset
6658 const char* LinearScanTimers::timer_name(int idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6659 switch (idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6660 case timer_do_nothing: return "Nothing (Time Check)";
a61af66fc99e Initial load
duke
parents:
diff changeset
6661 case timer_number_instructions: return "Number Instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6662 case timer_compute_local_live_sets: return "Local Live Sets";
a61af66fc99e Initial load
duke
parents:
diff changeset
6663 case timer_compute_global_live_sets: return "Global Live Sets";
a61af66fc99e Initial load
duke
parents:
diff changeset
6664 case timer_build_intervals: return "Build Intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6665 case timer_sort_intervals_before: return "Sort Intervals Before";
a61af66fc99e Initial load
duke
parents:
diff changeset
6666 case timer_allocate_registers: return "Allocate Registers";
a61af66fc99e Initial load
duke
parents:
diff changeset
6667 case timer_resolve_data_flow: return "Resolve Data Flow";
a61af66fc99e Initial load
duke
parents:
diff changeset
6668 case timer_sort_intervals_after: return "Sort Intervals After";
a61af66fc99e Initial load
duke
parents:
diff changeset
6669 case timer_eliminate_spill_moves: return "Spill optimization";
a61af66fc99e Initial load
duke
parents:
diff changeset
6670 case timer_assign_reg_num: return "Assign Reg Num";
a61af66fc99e Initial load
duke
parents:
diff changeset
6671 case timer_allocate_fpu_stack: return "Allocate FPU Stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6672 case timer_optimize_lir: return "Optimize LIR";
a61af66fc99e Initial load
duke
parents:
diff changeset
6673 default: ShouldNotReachHere(); return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6674 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6675 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6676
a61af66fc99e Initial load
duke
parents:
diff changeset
6677 void LinearScanTimers::begin_method() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6678 if (TimeEachLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6679 // reset all timers to measure only current method
a61af66fc99e Initial load
duke
parents:
diff changeset
6680 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6681 timer(i)->reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
6682 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6683 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6684 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6685
a61af66fc99e Initial load
duke
parents:
diff changeset
6686 void LinearScanTimers::end_method(LinearScan* allocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6687 if (TimeEachLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6688
a61af66fc99e Initial load
duke
parents:
diff changeset
6689 double c = timer(timer_do_nothing)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6690 double total = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6691 for (int i = 1; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6692 total += timer(i)->seconds() - c;
a61af66fc99e Initial load
duke
parents:
diff changeset
6693 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6694
a61af66fc99e Initial load
duke
parents:
diff changeset
6695 if (total >= 0.0005) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6696 // print all information in one line for automatic processing
a61af66fc99e Initial load
duke
parents:
diff changeset
6697 tty->print("@"); allocator->compilation()->method()->print_name();
a61af66fc99e Initial load
duke
parents:
diff changeset
6698
a61af66fc99e Initial load
duke
parents:
diff changeset
6699 tty->print("@ %d ", allocator->compilation()->method()->code_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
6700 tty->print("@ %d ", allocator->block_at(allocator->block_count() - 1)->last_lir_instruction_id() / 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
6701 tty->print("@ %d ", allocator->block_count());
a61af66fc99e Initial load
duke
parents:
diff changeset
6702 tty->print("@ %d ", allocator->num_virtual_regs());
a61af66fc99e Initial load
duke
parents:
diff changeset
6703 tty->print("@ %d ", allocator->interval_count());
a61af66fc99e Initial load
duke
parents:
diff changeset
6704 tty->print("@ %d ", allocator->_num_calls);
a61af66fc99e Initial load
duke
parents:
diff changeset
6705 tty->print("@ %d ", allocator->num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
6706
a61af66fc99e Initial load
duke
parents:
diff changeset
6707 tty->print("@ %6.6f ", total);
a61af66fc99e Initial load
duke
parents:
diff changeset
6708 for (int i = 1; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6709 tty->print("@ %4.1f ", ((timer(i)->seconds() - c) / total) * 100);
a61af66fc99e Initial load
duke
parents:
diff changeset
6710 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6711 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6712 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6713 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6714 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6715
a61af66fc99e Initial load
duke
parents:
diff changeset
6716 void LinearScanTimers::print(double total_time) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6717 if (TimeLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6718 // correction value: sum of dummy-timer that only measures the time that
a61af66fc99e Initial load
duke
parents:
diff changeset
6719 // is necesary to start and stop itself
a61af66fc99e Initial load
duke
parents:
diff changeset
6720 double c = timer(timer_do_nothing)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6721
a61af66fc99e Initial load
duke
parents:
diff changeset
6722 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6723 double t = timer(i)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6724 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);
a61af66fc99e Initial load
duke
parents:
diff changeset
6725 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6726 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6727 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6728
a61af66fc99e Initial load
duke
parents:
diff changeset
6729 #endif // #ifndef PRODUCT