annotate src/share/vm/c1/c1_LinearScan.cpp @ 1994:6cd6d394f280

7001033: assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed()) 7002546: regression on SpecJbb2005 on 7b118 comparing to 7b117 on small heaps Summary: Relaxed assertion checking related to incremental_collection_failed flag to allow for ExplicitGCInvokesConcurrent behaviour where we do not want a failing scavenge to bail to a stop-world collection. Parameterized incremental_collection_will_fail() so we can selectively use, or not use, as appropriate, the statistical prediction at specific use sites. This essentially reverts the scavenge bail-out logic to what it was prior to some recent changes that had inadvertently started using the statistical prediction which can be noisy in the presence of bursty loads. Added some associated verbose non-product debugging messages. Reviewed-by: johnc, tonyp
author ysr
date Tue, 07 Dec 2010 21:55:53 -0800
parents f95d63e2154a
children ac637b7220d1
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1397
diff changeset
2 * Copyright (c) 2005, 2010, 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
0
a61af66fc99e Initial load
duke
parents:
diff changeset
44
a61af66fc99e Initial load
duke
parents:
diff changeset
45
a61af66fc99e Initial load
duke
parents:
diff changeset
46 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
47
a61af66fc99e Initial load
duke
parents:
diff changeset
48 static LinearScanStatistic _stat_before_alloc;
a61af66fc99e Initial load
duke
parents:
diff changeset
49 static LinearScanStatistic _stat_after_asign;
a61af66fc99e Initial load
duke
parents:
diff changeset
50 static LinearScanStatistic _stat_final;
a61af66fc99e Initial load
duke
parents:
diff changeset
51
a61af66fc99e Initial load
duke
parents:
diff changeset
52 static LinearScanTimers _total_timer;
a61af66fc99e Initial load
duke
parents:
diff changeset
53
a61af66fc99e Initial load
duke
parents:
diff changeset
54 // helper macro for short definition of timer
a61af66fc99e Initial load
duke
parents:
diff changeset
55 #define TIME_LINEAR_SCAN(timer_name) TraceTime _block_timer("", _total_timer.timer(LinearScanTimers::timer_name), TimeLinearScan || TimeEachLinearScan, Verbose);
a61af66fc99e Initial load
duke
parents:
diff changeset
56
a61af66fc99e Initial load
duke
parents:
diff changeset
57 // helper macro for short definition of trace-output inside code
a61af66fc99e Initial load
duke
parents:
diff changeset
58 #define TRACE_LINEAR_SCAN(level, code) \
a61af66fc99e Initial load
duke
parents:
diff changeset
59 if (TraceLinearScanLevel >= level) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
60 code; \
a61af66fc99e Initial load
duke
parents:
diff changeset
61 }
a61af66fc99e Initial load
duke
parents:
diff changeset
62
a61af66fc99e Initial load
duke
parents:
diff changeset
63 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
64
a61af66fc99e Initial load
duke
parents:
diff changeset
65 #define TIME_LINEAR_SCAN(timer_name)
a61af66fc99e Initial load
duke
parents:
diff changeset
66 #define TRACE_LINEAR_SCAN(level, code)
a61af66fc99e Initial load
duke
parents:
diff changeset
67
a61af66fc99e Initial load
duke
parents:
diff changeset
68 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
69
a61af66fc99e Initial load
duke
parents:
diff changeset
70 // Map BasicType to spill size in 32-bit words, matching VMReg's notion of words
a61af66fc99e Initial load
duke
parents:
diff changeset
71 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
72 static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 0, 1, -1};
a61af66fc99e Initial load
duke
parents:
diff changeset
73 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
74 static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, -1};
a61af66fc99e Initial load
duke
parents:
diff changeset
75 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
76
a61af66fc99e Initial load
duke
parents:
diff changeset
77
a61af66fc99e Initial load
duke
parents:
diff changeset
78 // Implementation of LinearScan
a61af66fc99e Initial load
duke
parents:
diff changeset
79
a61af66fc99e Initial load
duke
parents:
diff changeset
80 LinearScan::LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map)
a61af66fc99e Initial load
duke
parents:
diff changeset
81 : _compilation(ir->compilation())
a61af66fc99e Initial load
duke
parents:
diff changeset
82 , _ir(ir)
a61af66fc99e Initial load
duke
parents:
diff changeset
83 , _gen(gen)
a61af66fc99e Initial load
duke
parents:
diff changeset
84 , _frame_map(frame_map)
a61af66fc99e Initial load
duke
parents:
diff changeset
85 , _num_virtual_regs(gen->max_virtual_register_number())
a61af66fc99e Initial load
duke
parents:
diff changeset
86 , _has_fpu_registers(false)
a61af66fc99e Initial load
duke
parents:
diff changeset
87 , _num_calls(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
88 , _max_spills(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
89 , _unused_spill_slot(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
90 , _intervals(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
91 , _new_intervals_from_allocation(new IntervalList())
a61af66fc99e Initial load
duke
parents:
diff changeset
92 , _sorted_intervals(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
93 , _lir_ops(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
94 , _block_of_op(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
95 , _has_info(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
96 , _has_call(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
97 , _scope_value_cache(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
98 , _interval_in_loop(0, 0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
99 , _cached_blocks(*ir->linear_scan_order())
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
100 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
101 , _fpu_stack_allocator(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
102 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
103 {
a61af66fc99e Initial load
duke
parents:
diff changeset
104 assert(this->ir() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
105 assert(this->compilation() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
106 assert(this->gen() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
107 assert(this->frame_map() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
108 }
a61af66fc99e Initial load
duke
parents:
diff changeset
109
a61af66fc99e Initial load
duke
parents:
diff changeset
110
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // ********** functions for converting LIR-Operands to register numbers
a61af66fc99e Initial load
duke
parents:
diff changeset
112 //
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // Emulate a flat register file comprising physical integer registers,
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // physical floating-point registers and virtual registers, in that order.
a61af66fc99e Initial load
duke
parents:
diff changeset
115 // Virtual registers already have appropriate numbers, since V0 is
a61af66fc99e Initial load
duke
parents:
diff changeset
116 // the number of physical registers.
a61af66fc99e Initial load
duke
parents:
diff changeset
117 // Returns -1 for hi word if opr is a single word operand.
a61af66fc99e Initial load
duke
parents:
diff changeset
118 //
a61af66fc99e Initial load
duke
parents:
diff changeset
119 // Note: the inverse operation (calculating an operand for register numbers)
a61af66fc99e Initial load
duke
parents:
diff changeset
120 // is done in calc_operand_for_interval()
a61af66fc99e Initial load
duke
parents:
diff changeset
121
a61af66fc99e Initial load
duke
parents:
diff changeset
122 int LinearScan::reg_num(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
123 assert(opr->is_register(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
124
a61af66fc99e Initial load
duke
parents:
diff changeset
125 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
126 assert(opr->vreg_number() >= nof_regs, "found a virtual register with a fixed-register number");
a61af66fc99e Initial load
duke
parents:
diff changeset
127 return opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
128 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
129 return opr->cpu_regnr();
a61af66fc99e Initial load
duke
parents:
diff changeset
130 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
131 return opr->cpu_regnrLo();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
132 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
133 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
134 return opr->fpu_regnr() + pd_first_xmm_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
135 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
136 return opr->fpu_regnrLo() + pd_first_xmm_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
137 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
138 } else if (opr->is_single_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
139 return opr->fpu_regnr() + pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
140 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
141 return opr->fpu_regnrLo() + pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
142 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
143 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
144 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
145 }
a61af66fc99e Initial load
duke
parents:
diff changeset
146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
147
a61af66fc99e Initial load
duke
parents:
diff changeset
148 int LinearScan::reg_numHi(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
149 assert(opr->is_register(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
150
a61af66fc99e Initial load
duke
parents:
diff changeset
151 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
152 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
153 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
154 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
155 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
156 return opr->cpu_regnrHi();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
157 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
158 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
159 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
160 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
161 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
162 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
163 } else if (opr->is_single_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
164 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
165 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
166 return opr->fpu_regnrHi() + pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
167 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
168 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
169 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
170 }
a61af66fc99e Initial load
duke
parents:
diff changeset
171 }
a61af66fc99e Initial load
duke
parents:
diff changeset
172
a61af66fc99e Initial load
duke
parents:
diff changeset
173
a61af66fc99e Initial load
duke
parents:
diff changeset
174 // ********** functions for classification of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
175
a61af66fc99e Initial load
duke
parents:
diff changeset
176 bool LinearScan::is_precolored_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
177 return i->reg_num() < LinearScan::nof_regs;
a61af66fc99e Initial load
duke
parents:
diff changeset
178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
179
a61af66fc99e Initial load
duke
parents:
diff changeset
180 bool LinearScan::is_virtual_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
181 return i->reg_num() >= LIR_OprDesc::vreg_base;
a61af66fc99e Initial load
duke
parents:
diff changeset
182 }
a61af66fc99e Initial load
duke
parents:
diff changeset
183
a61af66fc99e Initial load
duke
parents:
diff changeset
184 bool LinearScan::is_precolored_cpu_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
185 return i->reg_num() < LinearScan::nof_cpu_regs;
a61af66fc99e Initial load
duke
parents:
diff changeset
186 }
a61af66fc99e Initial load
duke
parents:
diff changeset
187
a61af66fc99e Initial load
duke
parents:
diff changeset
188 bool LinearScan::is_virtual_cpu_interval(const Interval* i) {
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
189 #if defined(__SOFTFP__) || defined(E500V2)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
190 return i->reg_num() >= LIR_OprDesc::vreg_base;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
191 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
192 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
193 #endif // __SOFTFP__ or E500V2
0
a61af66fc99e Initial load
duke
parents:
diff changeset
194 }
a61af66fc99e Initial load
duke
parents:
diff changeset
195
a61af66fc99e Initial load
duke
parents:
diff changeset
196 bool LinearScan::is_precolored_fpu_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
197 return i->reg_num() >= LinearScan::nof_cpu_regs && i->reg_num() < LinearScan::nof_regs;
a61af66fc99e Initial load
duke
parents:
diff changeset
198 }
a61af66fc99e Initial load
duke
parents:
diff changeset
199
a61af66fc99e Initial load
duke
parents:
diff changeset
200 bool LinearScan::is_virtual_fpu_interval(const Interval* i) {
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
201 #if defined(__SOFTFP__) || defined(E500V2)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
202 return false;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
203 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
204 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
205 #endif // __SOFTFP__ or E500V2
0
a61af66fc99e Initial load
duke
parents:
diff changeset
206 }
a61af66fc99e Initial load
duke
parents:
diff changeset
207
a61af66fc99e Initial load
duke
parents:
diff changeset
208 bool LinearScan::is_in_fpu_register(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
209 // fixed intervals not needed for FPU stack allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
210 return i->reg_num() >= nof_regs && pd_first_fpu_reg <= i->assigned_reg() && i->assigned_reg() <= pd_last_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
211 }
a61af66fc99e Initial load
duke
parents:
diff changeset
212
a61af66fc99e Initial load
duke
parents:
diff changeset
213 bool LinearScan::is_oop_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
214 // fixed intervals never contain oops
a61af66fc99e Initial load
duke
parents:
diff changeset
215 return i->reg_num() >= nof_regs && i->type() == T_OBJECT;
a61af66fc99e Initial load
duke
parents:
diff changeset
216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
217
a61af66fc99e Initial load
duke
parents:
diff changeset
218
a61af66fc99e Initial load
duke
parents:
diff changeset
219 // ********** General helper functions
a61af66fc99e Initial load
duke
parents:
diff changeset
220
a61af66fc99e Initial load
duke
parents:
diff changeset
221 // compute next unused stack index that can be used for spilling
a61af66fc99e Initial load
duke
parents:
diff changeset
222 int LinearScan::allocate_spill_slot(bool double_word) {
a61af66fc99e Initial load
duke
parents:
diff changeset
223 int spill_slot;
a61af66fc99e Initial load
duke
parents:
diff changeset
224 if (double_word) {
a61af66fc99e Initial load
duke
parents:
diff changeset
225 if ((_max_spills & 1) == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
226 // alignment of double-word values
a61af66fc99e Initial load
duke
parents:
diff changeset
227 // the hole because of the alignment is filled with the next single-word value
a61af66fc99e Initial load
duke
parents:
diff changeset
228 assert(_unused_spill_slot == -1, "wasting a spill slot");
a61af66fc99e Initial load
duke
parents:
diff changeset
229 _unused_spill_slot = _max_spills;
a61af66fc99e Initial load
duke
parents:
diff changeset
230 _max_spills++;
a61af66fc99e Initial load
duke
parents:
diff changeset
231 }
a61af66fc99e Initial load
duke
parents:
diff changeset
232 spill_slot = _max_spills;
a61af66fc99e Initial load
duke
parents:
diff changeset
233 _max_spills += 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
234
a61af66fc99e Initial load
duke
parents:
diff changeset
235 } else if (_unused_spill_slot != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
236 // re-use hole that was the result of a previous double-word alignment
a61af66fc99e Initial load
duke
parents:
diff changeset
237 spill_slot = _unused_spill_slot;
a61af66fc99e Initial load
duke
parents:
diff changeset
238 _unused_spill_slot = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
239
a61af66fc99e Initial load
duke
parents:
diff changeset
240 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
241 spill_slot = _max_spills;
a61af66fc99e Initial load
duke
parents:
diff changeset
242 _max_spills++;
a61af66fc99e Initial load
duke
parents:
diff changeset
243 }
a61af66fc99e Initial load
duke
parents:
diff changeset
244
a61af66fc99e Initial load
duke
parents:
diff changeset
245 int result = spill_slot + LinearScan::nof_regs + frame_map()->argcount();
a61af66fc99e Initial load
duke
parents:
diff changeset
246
a61af66fc99e Initial load
duke
parents:
diff changeset
247 // the class OopMapValue uses only 11 bits for storing the name of the
a61af66fc99e Initial load
duke
parents:
diff changeset
248 // oop location. So a stack slot bigger than 2^11 leads to an overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
249 // that is not reported in product builds. Prevent this by checking the
a61af66fc99e Initial load
duke
parents:
diff changeset
250 // spill slot here (altough this value and the later used location name
a61af66fc99e Initial load
duke
parents:
diff changeset
251 // are slightly different)
a61af66fc99e Initial load
duke
parents:
diff changeset
252 if (result > 2000) {
a61af66fc99e Initial load
duke
parents:
diff changeset
253 bailout("too many stack slots used");
a61af66fc99e Initial load
duke
parents:
diff changeset
254 }
a61af66fc99e Initial load
duke
parents:
diff changeset
255
a61af66fc99e Initial load
duke
parents:
diff changeset
256 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
258
a61af66fc99e Initial load
duke
parents:
diff changeset
259 void LinearScan::assign_spill_slot(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
260 // assign the canonical spill slot of the parent (if a part of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
261 // is already spilled) or allocate a new spill slot
a61af66fc99e Initial load
duke
parents:
diff changeset
262 if (it->canonical_spill_slot() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
263 it->assign_reg(it->canonical_spill_slot());
a61af66fc99e Initial load
duke
parents:
diff changeset
264 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
265 int spill = allocate_spill_slot(type2spill_size[it->type()] == 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
266 it->set_canonical_spill_slot(spill);
a61af66fc99e Initial load
duke
parents:
diff changeset
267 it->assign_reg(spill);
a61af66fc99e Initial load
duke
parents:
diff changeset
268 }
a61af66fc99e Initial load
duke
parents:
diff changeset
269 }
a61af66fc99e Initial load
duke
parents:
diff changeset
270
a61af66fc99e Initial load
duke
parents:
diff changeset
271 void LinearScan::propagate_spill_slots() {
a61af66fc99e Initial load
duke
parents:
diff changeset
272 if (!frame_map()->finalize_frame(max_spills())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
273 bailout("frame too large");
a61af66fc99e Initial load
duke
parents:
diff changeset
274 }
a61af66fc99e Initial load
duke
parents:
diff changeset
275 }
a61af66fc99e Initial load
duke
parents:
diff changeset
276
a61af66fc99e Initial load
duke
parents:
diff changeset
277 // create a new interval with a predefined reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
278 // (only used for parent intervals that are created during the building phase)
a61af66fc99e Initial load
duke
parents:
diff changeset
279 Interval* LinearScan::create_interval(int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
280 assert(_intervals.at(reg_num) == NULL, "overwriting exisiting interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
281
a61af66fc99e Initial load
duke
parents:
diff changeset
282 Interval* interval = new Interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
283 _intervals.at_put(reg_num, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
284
a61af66fc99e Initial load
duke
parents:
diff changeset
285 // assign register number for precolored intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
286 if (reg_num < LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
287 interval->assign_reg(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
288 }
a61af66fc99e Initial load
duke
parents:
diff changeset
289 return interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
290 }
a61af66fc99e Initial load
duke
parents:
diff changeset
291
a61af66fc99e Initial load
duke
parents:
diff changeset
292 // assign a new reg_num to the interval and append it to the list of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
293 // (only used for child intervals that are created during register allocation)
a61af66fc99e Initial load
duke
parents:
diff changeset
294 void LinearScan::append_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
295 it->set_reg_num(_intervals.length());
a61af66fc99e Initial load
duke
parents:
diff changeset
296 _intervals.append(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
297 _new_intervals_from_allocation->append(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
298 }
a61af66fc99e Initial load
duke
parents:
diff changeset
299
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // copy the vreg-flags if an interval is split
a61af66fc99e Initial load
duke
parents:
diff changeset
301 void LinearScan::copy_register_flags(Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
302 if (gen()->is_vreg_flag_set(from->reg_num(), LIRGenerator::byte_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
303 gen()->set_vreg_flag(to->reg_num(), LIRGenerator::byte_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
304 }
a61af66fc99e Initial load
duke
parents:
diff changeset
305 if (gen()->is_vreg_flag_set(from->reg_num(), LIRGenerator::callee_saved)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
306 gen()->set_vreg_flag(to->reg_num(), LIRGenerator::callee_saved);
a61af66fc99e Initial load
duke
parents:
diff changeset
307 }
a61af66fc99e Initial load
duke
parents:
diff changeset
308
a61af66fc99e Initial load
duke
parents:
diff changeset
309 // Note: do not copy the must_start_in_memory flag because it is not necessary for child
a61af66fc99e Initial load
duke
parents:
diff changeset
310 // intervals (only the very beginning of the interval must be in memory)
a61af66fc99e Initial load
duke
parents:
diff changeset
311 }
a61af66fc99e Initial load
duke
parents:
diff changeset
312
a61af66fc99e Initial load
duke
parents:
diff changeset
313
a61af66fc99e Initial load
duke
parents:
diff changeset
314 // ********** spill move optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
315 // eliminate moves from register to stack if stack slot is known to be correct
a61af66fc99e Initial load
duke
parents:
diff changeset
316
a61af66fc99e Initial load
duke
parents:
diff changeset
317 // called during building of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
318 void LinearScan::change_spill_definition_pos(Interval* interval, int def_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
319 assert(interval->is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
320
a61af66fc99e Initial load
duke
parents:
diff changeset
321 switch (interval->spill_state()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
322 case noDefinitionFound:
a61af66fc99e Initial load
duke
parents:
diff changeset
323 assert(interval->spill_definition_pos() == -1, "must no be set before");
a61af66fc99e Initial load
duke
parents:
diff changeset
324 interval->set_spill_definition_pos(def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
325 interval->set_spill_state(oneDefinitionFound);
a61af66fc99e Initial load
duke
parents:
diff changeset
326 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
327
a61af66fc99e Initial load
duke
parents:
diff changeset
328 case oneDefinitionFound:
a61af66fc99e Initial load
duke
parents:
diff changeset
329 assert(def_pos <= interval->spill_definition_pos(), "positions are processed in reverse order when intervals are created");
a61af66fc99e Initial load
duke
parents:
diff changeset
330 if (def_pos < interval->spill_definition_pos() - 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
331 // second definition found, so no spill optimization possible for this interval
a61af66fc99e Initial load
duke
parents:
diff changeset
332 interval->set_spill_state(noOptimization);
a61af66fc99e Initial load
duke
parents:
diff changeset
333 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
334 // two consecutive definitions (because of two-operand LIR form)
a61af66fc99e Initial load
duke
parents:
diff changeset
335 assert(block_of_op_with_id(def_pos) == block_of_op_with_id(interval->spill_definition_pos()), "block must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
336 }
a61af66fc99e Initial load
duke
parents:
diff changeset
337 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
338
a61af66fc99e Initial load
duke
parents:
diff changeset
339 case noOptimization:
a61af66fc99e Initial load
duke
parents:
diff changeset
340 // nothing to do
a61af66fc99e Initial load
duke
parents:
diff changeset
341 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
342
a61af66fc99e Initial load
duke
parents:
diff changeset
343 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
344 assert(false, "other states not allowed at this time");
a61af66fc99e Initial load
duke
parents:
diff changeset
345 }
a61af66fc99e Initial load
duke
parents:
diff changeset
346 }
a61af66fc99e Initial load
duke
parents:
diff changeset
347
a61af66fc99e Initial load
duke
parents:
diff changeset
348 // called during register allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
349 void LinearScan::change_spill_state(Interval* interval, int spill_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
350 switch (interval->spill_state()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
351 case oneDefinitionFound: {
a61af66fc99e Initial load
duke
parents:
diff changeset
352 int def_loop_depth = block_of_op_with_id(interval->spill_definition_pos())->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
353 int spill_loop_depth = block_of_op_with_id(spill_pos)->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
354
a61af66fc99e Initial load
duke
parents:
diff changeset
355 if (def_loop_depth < spill_loop_depth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
356 // the loop depth of the spilling position is higher then the loop depth
a61af66fc99e Initial load
duke
parents:
diff changeset
357 // at the definition of the interval -> move write to memory out of loop
a61af66fc99e Initial load
duke
parents:
diff changeset
358 // by storing at definitin of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
359 interval->set_spill_state(storeAtDefinition);
a61af66fc99e Initial load
duke
parents:
diff changeset
360 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
361 // the interval is currently spilled only once, so for now there is no
a61af66fc99e Initial load
duke
parents:
diff changeset
362 // reason to store the interval at the definition
a61af66fc99e Initial load
duke
parents:
diff changeset
363 interval->set_spill_state(oneMoveInserted);
a61af66fc99e Initial load
duke
parents:
diff changeset
364 }
a61af66fc99e Initial load
duke
parents:
diff changeset
365 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
366 }
a61af66fc99e Initial load
duke
parents:
diff changeset
367
a61af66fc99e Initial load
duke
parents:
diff changeset
368 case oneMoveInserted: {
a61af66fc99e Initial load
duke
parents:
diff changeset
369 // the interval is spilled more then once, so it is better to store it to
a61af66fc99e Initial load
duke
parents:
diff changeset
370 // memory at the definition
a61af66fc99e Initial load
duke
parents:
diff changeset
371 interval->set_spill_state(storeAtDefinition);
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 storeAtDefinition:
a61af66fc99e Initial load
duke
parents:
diff changeset
376 case startInMemory:
a61af66fc99e Initial load
duke
parents:
diff changeset
377 case noOptimization:
a61af66fc99e Initial load
duke
parents:
diff changeset
378 case noDefinitionFound:
a61af66fc99e Initial load
duke
parents:
diff changeset
379 // nothing to do
a61af66fc99e Initial load
duke
parents:
diff changeset
380 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
381
a61af66fc99e Initial load
duke
parents:
diff changeset
382 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
383 assert(false, "other states not allowed at this time");
a61af66fc99e Initial load
duke
parents:
diff changeset
384 }
a61af66fc99e Initial load
duke
parents:
diff changeset
385 }
a61af66fc99e Initial load
duke
parents:
diff changeset
386
a61af66fc99e Initial load
duke
parents:
diff changeset
387
a61af66fc99e Initial load
duke
parents:
diff changeset
388 bool LinearScan::must_store_at_definition(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
389 return i->is_split_parent() && i->spill_state() == storeAtDefinition;
a61af66fc99e Initial load
duke
parents:
diff changeset
390 }
a61af66fc99e Initial load
duke
parents:
diff changeset
391
a61af66fc99e Initial load
duke
parents:
diff changeset
392 // called once before asignment of register numbers
a61af66fc99e Initial load
duke
parents:
diff changeset
393 void LinearScan::eliminate_spill_moves() {
a61af66fc99e Initial load
duke
parents:
diff changeset
394 TIME_LINEAR_SCAN(timer_eliminate_spill_moves);
a61af66fc99e Initial load
duke
parents:
diff changeset
395 TRACE_LINEAR_SCAN(3, tty->print_cr("***** Eliminating unnecessary spill moves"));
a61af66fc99e Initial load
duke
parents:
diff changeset
396
a61af66fc99e Initial load
duke
parents:
diff changeset
397 // collect all intervals that must be stored after their definion.
a61af66fc99e Initial load
duke
parents:
diff changeset
398 // the list is sorted by Interval::spill_definition_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
399 Interval* interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
400 Interval* temp_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
401 create_unhandled_lists(&interval, &temp_list, must_store_at_definition, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
402
a61af66fc99e Initial load
duke
parents:
diff changeset
403 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
404 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
405 Interval* temp = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
406 while (temp != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
407 assert(temp->spill_definition_pos() > 0, "invalid spill definition pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
408 if (prev != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
409 assert(temp->from() >= prev->from(), "intervals not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
410 assert(temp->spill_definition_pos() >= prev->spill_definition_pos(), "when intervals are sorted by from, then they must also be sorted by spill_definition_pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
411 }
a61af66fc99e Initial load
duke
parents:
diff changeset
412
a61af66fc99e Initial load
duke
parents:
diff changeset
413 assert(temp->canonical_spill_slot() >= LinearScan::nof_regs, "interval has no spill slot assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
414 assert(temp->spill_definition_pos() >= temp->from(), "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
415 assert(temp->spill_definition_pos() <= temp->from() + 2, "only intervals defined once at their start-pos can be optimized");
a61af66fc99e Initial load
duke
parents:
diff changeset
416
a61af66fc99e Initial load
duke
parents:
diff changeset
417 TRACE_LINEAR_SCAN(4, tty->print_cr("interval %d (from %d to %d) must be stored at %d", temp->reg_num(), temp->from(), temp->to(), temp->spill_definition_pos()));
a61af66fc99e Initial load
duke
parents:
diff changeset
418
a61af66fc99e Initial load
duke
parents:
diff changeset
419 temp = temp->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
420 }
a61af66fc99e Initial load
duke
parents:
diff changeset
421 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
422
a61af66fc99e Initial load
duke
parents:
diff changeset
423 LIR_InsertionBuffer insertion_buffer;
a61af66fc99e Initial load
duke
parents:
diff changeset
424 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
425 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
426 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
427 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
428 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
429 bool has_new = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
430
a61af66fc99e Initial load
duke
parents:
diff changeset
431 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
432 for (int j = 1; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
433 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
434 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
435
a61af66fc99e Initial load
duke
parents:
diff changeset
436 if (op_id == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
437 // remove move from register to stack if the stack slot is guaranteed to be correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
438 // only moves that have been inserted by LinearScan can be removed.
a61af66fc99e Initial load
duke
parents:
diff changeset
439 assert(op->code() == lir_move, "only moves can have a op_id of -1");
a61af66fc99e Initial load
duke
parents:
diff changeset
440 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
441 assert(op->as_Op1()->result_opr()->is_virtual(), "LinearScan inserts only moves to virtual registers");
a61af66fc99e Initial load
duke
parents:
diff changeset
442
a61af66fc99e Initial load
duke
parents:
diff changeset
443 LIR_Op1* op1 = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
444 Interval* interval = interval_at(op1->result_opr()->vreg_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
445
a61af66fc99e Initial load
duke
parents:
diff changeset
446 if (interval->assigned_reg() >= LinearScan::nof_regs && interval->always_in_memory()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
447 // move target is a stack slot that is always correct, so eliminate instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
448 TRACE_LINEAR_SCAN(4, tty->print_cr("eliminating move from interval %d to %d", op1->in_opr()->vreg_number(), op1->result_opr()->vreg_number()));
a61af66fc99e Initial load
duke
parents:
diff changeset
449 instructions->at_put(j, NULL); // NULL-instructions are deleted by assign_reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
450 }
a61af66fc99e Initial load
duke
parents:
diff changeset
451
a61af66fc99e Initial load
duke
parents:
diff changeset
452 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
453 // insert move from register to stack just after the beginning of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
454 assert(interval == Interval::end() || interval->spill_definition_pos() >= op_id, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
455 assert(interval == Interval::end() || (interval->is_split_parent() && interval->spill_state() == storeAtDefinition), "invalid interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
456
a61af66fc99e Initial load
duke
parents:
diff changeset
457 while (interval != Interval::end() && interval->spill_definition_pos() == op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
458 if (!has_new) {
a61af66fc99e Initial load
duke
parents:
diff changeset
459 // prepare insertion buffer (appended when all instructions of the block are processed)
a61af66fc99e Initial load
duke
parents:
diff changeset
460 insertion_buffer.init(block->lir());
a61af66fc99e Initial load
duke
parents:
diff changeset
461 has_new = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
462 }
a61af66fc99e Initial load
duke
parents:
diff changeset
463
a61af66fc99e Initial load
duke
parents:
diff changeset
464 LIR_Opr from_opr = operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
465 LIR_Opr to_opr = canonical_spill_opr(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
466 assert(from_opr->is_fixed_cpu() || from_opr->is_fixed_fpu(), "from operand must be a register");
a61af66fc99e Initial load
duke
parents:
diff changeset
467 assert(to_opr->is_stack(), "to operand must be a stack slot");
a61af66fc99e Initial load
duke
parents:
diff changeset
468
a61af66fc99e Initial load
duke
parents:
diff changeset
469 insertion_buffer.move(j, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
470 TRACE_LINEAR_SCAN(4, tty->print_cr("inserting move after definition of interval %d to stack slot %d at op_id %d", interval->reg_num(), interval->canonical_spill_slot() - LinearScan::nof_regs, op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
471
a61af66fc99e Initial load
duke
parents:
diff changeset
472 interval = interval->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
474 }
a61af66fc99e Initial load
duke
parents:
diff changeset
475 } // end of instruction iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
476
a61af66fc99e Initial load
duke
parents:
diff changeset
477 if (has_new) {
a61af66fc99e Initial load
duke
parents:
diff changeset
478 block->lir()->append(&insertion_buffer);
a61af66fc99e Initial load
duke
parents:
diff changeset
479 }
a61af66fc99e Initial load
duke
parents:
diff changeset
480 } // end of block iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
481
a61af66fc99e Initial load
duke
parents:
diff changeset
482 assert(interval == Interval::end(), "missed an interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
483 }
a61af66fc99e Initial load
duke
parents:
diff changeset
484
a61af66fc99e Initial load
duke
parents:
diff changeset
485
a61af66fc99e Initial load
duke
parents:
diff changeset
486 // ********** Phase 1: number all instructions in all blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
487 // Compute depth-first and linear scan block orders, and number LIR_Op nodes for linear scan.
a61af66fc99e Initial load
duke
parents:
diff changeset
488
a61af66fc99e Initial load
duke
parents:
diff changeset
489 void LinearScan::number_instructions() {
a61af66fc99e Initial load
duke
parents:
diff changeset
490 {
a61af66fc99e Initial load
duke
parents:
diff changeset
491 // dummy-timer to measure the cost of the timer itself
a61af66fc99e Initial load
duke
parents:
diff changeset
492 // (this time is then subtracted from all other timers to get the real value)
a61af66fc99e Initial load
duke
parents:
diff changeset
493 TIME_LINEAR_SCAN(timer_do_nothing);
a61af66fc99e Initial load
duke
parents:
diff changeset
494 }
a61af66fc99e Initial load
duke
parents:
diff changeset
495 TIME_LINEAR_SCAN(timer_number_instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
496
a61af66fc99e Initial load
duke
parents:
diff changeset
497 // Assign IDs to LIR nodes and build a mapping, lir_ops, from ID to LIR_Op node.
a61af66fc99e Initial load
duke
parents:
diff changeset
498 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
499 int num_instructions = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
500 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
501 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
502 num_instructions += block_at(i)->lir()->instructions_list()->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
503 }
a61af66fc99e Initial load
duke
parents:
diff changeset
504
a61af66fc99e Initial load
duke
parents:
diff changeset
505 // initialize with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
506 _lir_ops = LIR_OpArray(num_instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
507 _block_of_op = BlockBeginArray(num_instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
508
a61af66fc99e Initial load
duke
parents:
diff changeset
509 int op_id = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
510 int idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
511
a61af66fc99e Initial load
duke
parents:
diff changeset
512 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
513 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
514 block->set_first_lir_instruction_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
515 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
516
a61af66fc99e Initial load
duke
parents:
diff changeset
517 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
518 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
519 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
520 op->set_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
521
a61af66fc99e Initial load
duke
parents:
diff changeset
522 _lir_ops.at_put(idx, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
523 _block_of_op.at_put(idx, block);
a61af66fc99e Initial load
duke
parents:
diff changeset
524 assert(lir_op_with_id(op_id) == op, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
525
a61af66fc99e Initial load
duke
parents:
diff changeset
526 idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
527 op_id += 2; // numbering of lir_ops by two
a61af66fc99e Initial load
duke
parents:
diff changeset
528 }
a61af66fc99e Initial load
duke
parents:
diff changeset
529 block->set_last_lir_instruction_id(op_id - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
530 }
a61af66fc99e Initial load
duke
parents:
diff changeset
531 assert(idx == num_instructions, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
532 assert(idx * 2 == op_id, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
533
a61af66fc99e Initial load
duke
parents:
diff changeset
534 _has_call = BitMap(num_instructions); _has_call.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
535 _has_info = BitMap(num_instructions); _has_info.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
536 }
a61af66fc99e Initial load
duke
parents:
diff changeset
537
a61af66fc99e Initial load
duke
parents:
diff changeset
538
a61af66fc99e Initial load
duke
parents:
diff changeset
539 // ********** Phase 2: compute local live sets separately for each block
a61af66fc99e Initial load
duke
parents:
diff changeset
540 // (sets live_gen and live_kill for each block)
a61af66fc99e Initial load
duke
parents:
diff changeset
541
a61af66fc99e Initial load
duke
parents:
diff changeset
542 void LinearScan::set_live_gen_kill(Value value, LIR_Op* op, BitMap& live_gen, BitMap& live_kill) {
a61af66fc99e Initial load
duke
parents:
diff changeset
543 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
544 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
545
a61af66fc99e Initial load
duke
parents:
diff changeset
546 // check some asumptions about debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
547 assert(!value->type()->is_illegal(), "if this local is used by the interpreter it shouldn't be of indeterminate type");
a61af66fc99e Initial load
duke
parents:
diff changeset
548 assert(con == NULL || opr->is_virtual() || opr->is_constant() || opr->is_illegal(), "asumption: Constant instructions have only constant operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
549 assert(con != NULL || opr->is_virtual(), "asumption: non-Constant instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
550
a61af66fc99e Initial load
duke
parents:
diff changeset
551 if ((con == NULL || con->is_pinned()) && opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
552 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
553 int reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
554 if (!live_kill.at(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
555 live_gen.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
556 TRACE_LINEAR_SCAN(4, tty->print_cr(" Setting live_gen for value %c%d, LIR op_id %d, register number %d", value->type()->tchar(), value->id(), op->id(), reg));
a61af66fc99e Initial load
duke
parents:
diff changeset
557 }
a61af66fc99e Initial load
duke
parents:
diff changeset
558 }
a61af66fc99e Initial load
duke
parents:
diff changeset
559 }
a61af66fc99e Initial load
duke
parents:
diff changeset
560
a61af66fc99e Initial load
duke
parents:
diff changeset
561
a61af66fc99e Initial load
duke
parents:
diff changeset
562 void LinearScan::compute_local_live_sets() {
a61af66fc99e Initial load
duke
parents:
diff changeset
563 TIME_LINEAR_SCAN(timer_compute_local_live_sets);
a61af66fc99e Initial load
duke
parents:
diff changeset
564
a61af66fc99e Initial load
duke
parents:
diff changeset
565 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
566 int live_size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
567 bool local_has_fpu_registers = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
568 int local_num_calls = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
569 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
570
a61af66fc99e Initial load
duke
parents:
diff changeset
571 BitMap2D local_interval_in_loop = BitMap2D(_num_virtual_regs, num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
572 local_interval_in_loop.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
573
a61af66fc99e Initial load
duke
parents:
diff changeset
574 // iterate all blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
575 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
576 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
577
a61af66fc99e Initial load
duke
parents:
diff changeset
578 BitMap live_gen(live_size); live_gen.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
579 BitMap live_kill(live_size); live_kill.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
580
a61af66fc99e Initial load
duke
parents:
diff changeset
581 if (block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
582 // Phi functions at the begin of an exception handler are
a61af66fc99e Initial load
duke
parents:
diff changeset
583 // implicitly defined (= killed) at the beginning of the block.
a61af66fc99e Initial load
duke
parents:
diff changeset
584 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
585 live_kill.set_bit(phi->operand()->vreg_number())
a61af66fc99e Initial load
duke
parents:
diff changeset
586 );
a61af66fc99e Initial load
duke
parents:
diff changeset
587 }
a61af66fc99e Initial load
duke
parents:
diff changeset
588
a61af66fc99e Initial load
duke
parents:
diff changeset
589 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
590 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
591
a61af66fc99e Initial load
duke
parents:
diff changeset
592 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
593 assert(visitor.no_operands(instructions->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
594 for (int j = 1; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
595 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
596
a61af66fc99e Initial load
duke
parents:
diff changeset
597 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
598 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
599
a61af66fc99e Initial load
duke
parents:
diff changeset
600 if (visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
601 _has_call.set_bit(op->id() >> 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
602 local_num_calls++;
a61af66fc99e Initial load
duke
parents:
diff changeset
603 }
a61af66fc99e Initial load
duke
parents:
diff changeset
604 if (visitor.info_count() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
605 _has_info.set_bit(op->id() >> 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
606 }
a61af66fc99e Initial load
duke
parents:
diff changeset
607
a61af66fc99e Initial load
duke
parents:
diff changeset
608 // iterate input operands of instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
609 int k, n, reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
610 n = visitor.opr_count(LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
611 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
612 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
613 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
614
a61af66fc99e Initial load
duke
parents:
diff changeset
615 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
616 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
617 reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
618 if (!live_kill.at(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
619 live_gen.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
620 TRACE_LINEAR_SCAN(4, tty->print_cr(" Setting live_gen for register %d at instruction %d", reg, op->id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
621 }
a61af66fc99e Initial load
duke
parents:
diff changeset
622 if (block->loop_index() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
623 local_interval_in_loop.set_bit(reg, block->loop_index());
a61af66fc99e Initial load
duke
parents:
diff changeset
624 }
a61af66fc99e Initial load
duke
parents:
diff changeset
625 local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
a61af66fc99e Initial load
duke
parents:
diff changeset
626 }
a61af66fc99e Initial load
duke
parents:
diff changeset
627
a61af66fc99e Initial load
duke
parents:
diff changeset
628 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
629 // fixed intervals are never live at block boundaries, so
a61af66fc99e Initial load
duke
parents:
diff changeset
630 // they need not be processed in live sets.
a61af66fc99e Initial load
duke
parents:
diff changeset
631 // this is checked by these assertions to be sure about it.
a61af66fc99e Initial load
duke
parents:
diff changeset
632 // the entry block may have incoming values in registers, which is ok.
a61af66fc99e Initial load
duke
parents:
diff changeset
633 if (!opr->is_virtual_register() && block != ir()->start()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
634 reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
635 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
636 assert(live_kill.at(reg), "using fixed register that is not defined in this block");
a61af66fc99e Initial load
duke
parents:
diff changeset
637 }
a61af66fc99e Initial load
duke
parents:
diff changeset
638 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
639 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
640 assert(live_kill.at(reg), "using fixed register that is not defined in this block");
a61af66fc99e Initial load
duke
parents:
diff changeset
641 }
a61af66fc99e Initial load
duke
parents:
diff changeset
642 }
a61af66fc99e Initial load
duke
parents:
diff changeset
643 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
645
a61af66fc99e Initial load
duke
parents:
diff changeset
646 // Add uses of live locals from interpreter's point of view for proper debug information generation
a61af66fc99e Initial load
duke
parents:
diff changeset
647 n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
648 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
649 CodeEmitInfo* info = visitor.info_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
650 ValueStack* stack = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
651 for_each_state_value(stack, value,
a61af66fc99e Initial load
duke
parents:
diff changeset
652 set_live_gen_kill(value, op, live_gen, live_kill)
a61af66fc99e Initial load
duke
parents:
diff changeset
653 );
a61af66fc99e Initial load
duke
parents:
diff changeset
654 }
a61af66fc99e Initial load
duke
parents:
diff changeset
655
a61af66fc99e Initial load
duke
parents:
diff changeset
656 // iterate temp operands of instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
657 n = visitor.opr_count(LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
658 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
659 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
660 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
661
a61af66fc99e Initial load
duke
parents:
diff changeset
662 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
663 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
664 reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
665 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
666 if (block->loop_index() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
667 local_interval_in_loop.set_bit(reg, block->loop_index());
a61af66fc99e Initial load
duke
parents:
diff changeset
668 }
a61af66fc99e Initial load
duke
parents:
diff changeset
669 local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
a61af66fc99e Initial load
duke
parents:
diff changeset
670 }
a61af66fc99e Initial load
duke
parents:
diff changeset
671
a61af66fc99e Initial load
duke
parents:
diff changeset
672 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
673 // fixed intervals are never live at block boundaries, so
a61af66fc99e Initial load
duke
parents:
diff changeset
674 // they need not be processed in live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
675 // process them only in debug mode so that this can be checked
a61af66fc99e Initial load
duke
parents:
diff changeset
676 if (!opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
677 reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
678 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
679 live_kill.set_bit(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
680 }
a61af66fc99e Initial load
duke
parents:
diff changeset
681 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
682 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
683 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
684 }
a61af66fc99e Initial load
duke
parents:
diff changeset
685 }
a61af66fc99e Initial load
duke
parents:
diff changeset
686 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
687 }
a61af66fc99e Initial load
duke
parents:
diff changeset
688
a61af66fc99e Initial load
duke
parents:
diff changeset
689 // iterate output operands of instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
690 n = visitor.opr_count(LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
691 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
692 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
693 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
694
a61af66fc99e Initial load
duke
parents:
diff changeset
695 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
696 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
697 reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
698 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
699 if (block->loop_index() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
700 local_interval_in_loop.set_bit(reg, block->loop_index());
a61af66fc99e Initial load
duke
parents:
diff changeset
701 }
a61af66fc99e Initial load
duke
parents:
diff changeset
702 local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
a61af66fc99e Initial load
duke
parents:
diff changeset
703 }
a61af66fc99e Initial load
duke
parents:
diff changeset
704
a61af66fc99e Initial load
duke
parents:
diff changeset
705 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
706 // fixed intervals are never live at block boundaries, so
a61af66fc99e Initial load
duke
parents:
diff changeset
707 // they need not be processed in live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
708 // process them only in debug mode so that this can be checked
a61af66fc99e Initial load
duke
parents:
diff changeset
709 if (!opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
710 reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
711 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
712 live_kill.set_bit(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
713 }
a61af66fc99e Initial load
duke
parents:
diff changeset
714 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
715 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
716 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
717 }
a61af66fc99e Initial load
duke
parents:
diff changeset
718 }
a61af66fc99e Initial load
duke
parents:
diff changeset
719 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
720 }
a61af66fc99e Initial load
duke
parents:
diff changeset
721 } // end of instruction iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
722
a61af66fc99e Initial load
duke
parents:
diff changeset
723 block->set_live_gen (live_gen);
a61af66fc99e Initial load
duke
parents:
diff changeset
724 block->set_live_kill(live_kill);
a61af66fc99e Initial load
duke
parents:
diff changeset
725 block->set_live_in (BitMap(live_size)); block->live_in().clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
726 block->set_live_out (BitMap(live_size)); block->live_out().clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
727
a61af66fc99e Initial load
duke
parents:
diff changeset
728 TRACE_LINEAR_SCAN(4, tty->print("live_gen B%d ", block->block_id()); print_bitmap(block->live_gen()));
a61af66fc99e Initial load
duke
parents:
diff changeset
729 TRACE_LINEAR_SCAN(4, tty->print("live_kill B%d ", block->block_id()); print_bitmap(block->live_kill()));
a61af66fc99e Initial load
duke
parents:
diff changeset
730 } // end of block iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
731
a61af66fc99e Initial load
duke
parents:
diff changeset
732 // propagate local calculated information into LinearScan object
a61af66fc99e Initial load
duke
parents:
diff changeset
733 _has_fpu_registers = local_has_fpu_registers;
a61af66fc99e Initial load
duke
parents:
diff changeset
734 compilation()->set_has_fpu_code(local_has_fpu_registers);
a61af66fc99e Initial load
duke
parents:
diff changeset
735
a61af66fc99e Initial load
duke
parents:
diff changeset
736 _num_calls = local_num_calls;
a61af66fc99e Initial load
duke
parents:
diff changeset
737 _interval_in_loop = local_interval_in_loop;
a61af66fc99e Initial load
duke
parents:
diff changeset
738 }
a61af66fc99e Initial load
duke
parents:
diff changeset
739
a61af66fc99e Initial load
duke
parents:
diff changeset
740
a61af66fc99e Initial load
duke
parents:
diff changeset
741 // ********** Phase 3: perform a backward dataflow analysis to compute global live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
742 // (sets live_in and live_out for each block)
a61af66fc99e Initial load
duke
parents:
diff changeset
743
a61af66fc99e Initial load
duke
parents:
diff changeset
744 void LinearScan::compute_global_live_sets() {
a61af66fc99e Initial load
duke
parents:
diff changeset
745 TIME_LINEAR_SCAN(timer_compute_global_live_sets);
a61af66fc99e Initial load
duke
parents:
diff changeset
746
a61af66fc99e Initial load
duke
parents:
diff changeset
747 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
748 bool change_occurred;
a61af66fc99e Initial load
duke
parents:
diff changeset
749 bool change_occurred_in_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
750 int iteration_count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
751 BitMap live_out(live_set_size()); live_out.clear(); // scratch set for calculations
a61af66fc99e Initial load
duke
parents:
diff changeset
752
a61af66fc99e Initial load
duke
parents:
diff changeset
753 // Perform a backward dataflow analysis to compute live_out and live_in for each block.
a61af66fc99e Initial load
duke
parents:
diff changeset
754 // The loop is executed until a fixpoint is reached (no changes in an iteration)
a61af66fc99e Initial load
duke
parents:
diff changeset
755 // Exception handlers must be processed because not all live values are
a61af66fc99e Initial load
duke
parents:
diff changeset
756 // present in the state array, e.g. because of global value numbering
a61af66fc99e Initial load
duke
parents:
diff changeset
757 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
758 change_occurred = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
759
a61af66fc99e Initial load
duke
parents:
diff changeset
760 // iterate all blocks in reverse order
a61af66fc99e Initial load
duke
parents:
diff changeset
761 for (int i = num_blocks - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
762 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
763
a61af66fc99e Initial load
duke
parents:
diff changeset
764 change_occurred_in_block = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
765
a61af66fc99e Initial load
duke
parents:
diff changeset
766 // live_out(block) is the union of live_in(sux), for successors sux of block
a61af66fc99e Initial load
duke
parents:
diff changeset
767 int n = block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
768 int e = block->number_of_exception_handlers();
a61af66fc99e Initial load
duke
parents:
diff changeset
769 if (n + e > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
770 // block has successors
a61af66fc99e Initial load
duke
parents:
diff changeset
771 if (n > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
772 live_out.set_from(block->sux_at(0)->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
773 for (int j = 1; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
774 live_out.set_union(block->sux_at(j)->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
775 }
a61af66fc99e Initial load
duke
parents:
diff changeset
776 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
777 live_out.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
778 }
a61af66fc99e Initial load
duke
parents:
diff changeset
779 for (int j = 0; j < e; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
780 live_out.set_union(block->exception_handler_at(j)->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
781 }
a61af66fc99e Initial load
duke
parents:
diff changeset
782
a61af66fc99e Initial load
duke
parents:
diff changeset
783 if (!block->live_out().is_same(live_out)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
784 // A change occurred. Swap the old and new live out sets to avoid copying.
a61af66fc99e Initial load
duke
parents:
diff changeset
785 BitMap temp = block->live_out();
a61af66fc99e Initial load
duke
parents:
diff changeset
786 block->set_live_out(live_out);
a61af66fc99e Initial load
duke
parents:
diff changeset
787 live_out = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
788
a61af66fc99e Initial load
duke
parents:
diff changeset
789 change_occurred = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
790 change_occurred_in_block = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
791 }
a61af66fc99e Initial load
duke
parents:
diff changeset
792 }
a61af66fc99e Initial load
duke
parents:
diff changeset
793
a61af66fc99e Initial load
duke
parents:
diff changeset
794 if (iteration_count == 0 || change_occurred_in_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
795 // live_in(block) is the union of live_gen(block) with (live_out(block) & !live_kill(block))
a61af66fc99e Initial load
duke
parents:
diff changeset
796 // note: live_in has to be computed only in first iteration or if live_out has changed!
a61af66fc99e Initial load
duke
parents:
diff changeset
797 BitMap live_in = block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
798 live_in.set_from(block->live_out());
a61af66fc99e Initial load
duke
parents:
diff changeset
799 live_in.set_difference(block->live_kill());
a61af66fc99e Initial load
duke
parents:
diff changeset
800 live_in.set_union(block->live_gen());
a61af66fc99e Initial load
duke
parents:
diff changeset
801 }
a61af66fc99e Initial load
duke
parents:
diff changeset
802
a61af66fc99e Initial load
duke
parents:
diff changeset
803 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
804 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
805 char c = ' ';
a61af66fc99e Initial load
duke
parents:
diff changeset
806 if (iteration_count == 0 || change_occurred_in_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
807 c = '*';
a61af66fc99e Initial load
duke
parents:
diff changeset
808 }
a61af66fc99e Initial load
duke
parents:
diff changeset
809 tty->print("(%d) live_in%c B%d ", iteration_count, c, block->block_id()); print_bitmap(block->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
810 tty->print("(%d) live_out%c B%d ", iteration_count, c, block->block_id()); print_bitmap(block->live_out());
a61af66fc99e Initial load
duke
parents:
diff changeset
811 }
a61af66fc99e Initial load
duke
parents:
diff changeset
812 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
813 }
a61af66fc99e Initial load
duke
parents:
diff changeset
814 iteration_count++;
a61af66fc99e Initial load
duke
parents:
diff changeset
815
a61af66fc99e Initial load
duke
parents:
diff changeset
816 if (change_occurred && iteration_count > 50) {
a61af66fc99e Initial load
duke
parents:
diff changeset
817 BAILOUT("too many iterations in compute_global_live_sets");
a61af66fc99e Initial load
duke
parents:
diff changeset
818 }
a61af66fc99e Initial load
duke
parents:
diff changeset
819 } while (change_occurred);
a61af66fc99e Initial load
duke
parents:
diff changeset
820
a61af66fc99e Initial load
duke
parents:
diff changeset
821
a61af66fc99e Initial load
duke
parents:
diff changeset
822 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
823 // check that fixed intervals are not live at block boundaries
a61af66fc99e Initial load
duke
parents:
diff changeset
824 // (live set must be empty at fixed intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
825 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
826 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
827 for (int j = 0; j < LIR_OprDesc::vreg_base; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
828 assert(block->live_in().at(j) == false, "live_in set of fixed register must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
829 assert(block->live_out().at(j) == false, "live_out set of fixed register must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
830 assert(block->live_gen().at(j) == false, "live_gen set of fixed register must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
831 }
a61af66fc99e Initial load
duke
parents:
diff changeset
832 }
a61af66fc99e Initial load
duke
parents:
diff changeset
833 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
834
a61af66fc99e Initial load
duke
parents:
diff changeset
835 // check that the live_in set of the first block is empty
a61af66fc99e Initial load
duke
parents:
diff changeset
836 BitMap live_in_args(ir()->start()->live_in().size());
a61af66fc99e Initial load
duke
parents:
diff changeset
837 live_in_args.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
838 if (!ir()->start()->live_in().is_same(live_in_args)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
839 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
840 tty->print_cr("Error: live_in set of first block must be empty (when this fails, virtual registers are used before they are defined)");
a61af66fc99e Initial load
duke
parents:
diff changeset
841 tty->print_cr("affected registers:");
a61af66fc99e Initial load
duke
parents:
diff changeset
842 print_bitmap(ir()->start()->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
843
a61af66fc99e Initial load
duke
parents:
diff changeset
844 // print some additional information to simplify debugging
a61af66fc99e Initial load
duke
parents:
diff changeset
845 for (unsigned int i = 0; i < ir()->start()->live_in().size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
846 if (ir()->start()->live_in().at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
847 Instruction* instr = gen()->instruction_for_vreg(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
848 tty->print_cr("* vreg %d (HIR instruction %c%d)", i, instr == NULL ? ' ' : instr->type()->tchar(), instr == NULL ? 0 : instr->id());
a61af66fc99e Initial load
duke
parents:
diff changeset
849
a61af66fc99e Initial load
duke
parents:
diff changeset
850 for (int j = 0; j < num_blocks; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
851 BlockBegin* block = block_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
852 if (block->live_gen().at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
853 tty->print_cr(" used in block B%d", block->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
854 }
a61af66fc99e Initial load
duke
parents:
diff changeset
855 if (block->live_kill().at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
856 tty->print_cr(" defined in block B%d", block->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
857 }
a61af66fc99e Initial load
duke
parents:
diff changeset
858 }
a61af66fc99e Initial load
duke
parents:
diff changeset
859 }
a61af66fc99e Initial load
duke
parents:
diff changeset
860 }
a61af66fc99e Initial load
duke
parents:
diff changeset
861
a61af66fc99e Initial load
duke
parents:
diff changeset
862 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
863 // when this fails, virtual registers are used before they are defined.
a61af66fc99e Initial load
duke
parents:
diff changeset
864 assert(false, "live_in set of first block must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
865 // bailout of if this occurs in product mode.
a61af66fc99e Initial load
duke
parents:
diff changeset
866 bailout("live_in set of first block not empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
867 }
a61af66fc99e Initial load
duke
parents:
diff changeset
868 }
a61af66fc99e Initial load
duke
parents:
diff changeset
869
a61af66fc99e Initial load
duke
parents:
diff changeset
870
a61af66fc99e Initial load
duke
parents:
diff changeset
871 // ********** Phase 4: build intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
872 // (fills the list _intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
873
a61af66fc99e Initial load
duke
parents:
diff changeset
874 void LinearScan::add_use(Value value, int from, int to, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
875 assert(!value->type()->is_illegal(), "if this value is used by the interpreter it shouldn't be of indeterminate type");
a61af66fc99e Initial load
duke
parents:
diff changeset
876 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
877 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
878
a61af66fc99e Initial load
duke
parents:
diff changeset
879 if ((con == NULL || con->is_pinned()) && opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
880 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
881 add_use(opr, from, to, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
882 }
a61af66fc99e Initial load
duke
parents:
diff changeset
883 }
a61af66fc99e Initial load
duke
parents:
diff changeset
884
a61af66fc99e Initial load
duke
parents:
diff changeset
885
a61af66fc99e Initial load
duke
parents:
diff changeset
886 void LinearScan::add_def(LIR_Opr opr, int def_pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
887 TRACE_LINEAR_SCAN(2, tty->print(" def "); opr->print(tty); tty->print_cr(" def_pos %d (%d)", def_pos, use_kind));
a61af66fc99e Initial load
duke
parents:
diff changeset
888 assert(opr->is_register(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
889
a61af66fc99e Initial load
duke
parents:
diff changeset
890 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
891 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
892 add_def(opr->vreg_number(), def_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
893
a61af66fc99e Initial load
duke
parents:
diff changeset
894 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
895 int reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
896 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
897 add_def(reg, def_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
898 }
a61af66fc99e Initial load
duke
parents:
diff changeset
899 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
900 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
901 add_def(reg, def_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
902 }
a61af66fc99e Initial load
duke
parents:
diff changeset
903 }
a61af66fc99e Initial load
duke
parents:
diff changeset
904 }
a61af66fc99e Initial load
duke
parents:
diff changeset
905
a61af66fc99e Initial load
duke
parents:
diff changeset
906 void LinearScan::add_use(LIR_Opr opr, int from, int to, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
907 TRACE_LINEAR_SCAN(2, tty->print(" use "); opr->print(tty); tty->print_cr(" from %d to %d (%d)", from, to, use_kind));
a61af66fc99e Initial load
duke
parents:
diff changeset
908 assert(opr->is_register(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
909
a61af66fc99e Initial load
duke
parents:
diff changeset
910 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
911 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
912 add_use(opr->vreg_number(), from, to, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
913
a61af66fc99e Initial load
duke
parents:
diff changeset
914 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
915 int reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
916 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
917 add_use(reg, from, to, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
918 }
a61af66fc99e Initial load
duke
parents:
diff changeset
919 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
920 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
921 add_use(reg, from, to, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
922 }
a61af66fc99e Initial load
duke
parents:
diff changeset
923 }
a61af66fc99e Initial load
duke
parents:
diff changeset
924 }
a61af66fc99e Initial load
duke
parents:
diff changeset
925
a61af66fc99e Initial load
duke
parents:
diff changeset
926 void LinearScan::add_temp(LIR_Opr opr, int temp_pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
927 TRACE_LINEAR_SCAN(2, tty->print(" temp "); opr->print(tty); tty->print_cr(" temp_pos %d (%d)", temp_pos, use_kind));
a61af66fc99e Initial load
duke
parents:
diff changeset
928 assert(opr->is_register(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
929
a61af66fc99e Initial load
duke
parents:
diff changeset
930 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
931 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
932 add_temp(opr->vreg_number(), temp_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
933
a61af66fc99e Initial load
duke
parents:
diff changeset
934 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
935 int reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
936 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
937 add_temp(reg, temp_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
938 }
a61af66fc99e Initial load
duke
parents:
diff changeset
939 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
940 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
941 add_temp(reg, temp_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
942 }
a61af66fc99e Initial load
duke
parents:
diff changeset
943 }
a61af66fc99e Initial load
duke
parents:
diff changeset
944 }
a61af66fc99e Initial load
duke
parents:
diff changeset
945
a61af66fc99e Initial load
duke
parents:
diff changeset
946
a61af66fc99e Initial load
duke
parents:
diff changeset
947 void LinearScan::add_def(int reg_num, int def_pos, IntervalUseKind use_kind, BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
948 Interval* interval = interval_at(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
949 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
950 assert(interval->reg_num() == reg_num, "wrong interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
951
a61af66fc99e Initial load
duke
parents:
diff changeset
952 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
953 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
954 }
a61af66fc99e Initial load
duke
parents:
diff changeset
955
a61af66fc99e Initial load
duke
parents:
diff changeset
956 Range* r = interval->first();
a61af66fc99e Initial load
duke
parents:
diff changeset
957 if (r->from() <= def_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
958 // Update the starting point (when a range is first created for a use, its
a61af66fc99e Initial load
duke
parents:
diff changeset
959 // start is the beginning of the current block until a def is encountered.)
a61af66fc99e Initial load
duke
parents:
diff changeset
960 r->set_from(def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
961 interval->add_use_pos(def_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
962
a61af66fc99e Initial load
duke
parents:
diff changeset
963 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
964 // Dead value - make vacuous interval
a61af66fc99e Initial load
duke
parents:
diff changeset
965 // also add use_kind for dead intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
966 interval->add_range(def_pos, def_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
967 interval->add_use_pos(def_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
968 TRACE_LINEAR_SCAN(2, tty->print_cr("Warning: def of reg %d at %d occurs without use", reg_num, def_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
969 }
a61af66fc99e Initial load
duke
parents:
diff changeset
970
a61af66fc99e Initial load
duke
parents:
diff changeset
971 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
972 // Dead value - make vacuous interval
a61af66fc99e Initial load
duke
parents:
diff changeset
973 // also add use_kind for dead intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
974 interval = create_interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
975 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
976 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
977 }
a61af66fc99e Initial load
duke
parents:
diff changeset
978
a61af66fc99e Initial load
duke
parents:
diff changeset
979 interval->add_range(def_pos, def_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
980 interval->add_use_pos(def_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
981 TRACE_LINEAR_SCAN(2, tty->print_cr("Warning: dead value %d at %d in live intervals", reg_num, def_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
982 }
a61af66fc99e Initial load
duke
parents:
diff changeset
983
a61af66fc99e Initial load
duke
parents:
diff changeset
984 change_spill_definition_pos(interval, def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
985 if (use_kind == noUse && interval->spill_state() <= startInMemory) {
a61af66fc99e Initial load
duke
parents:
diff changeset
986 // detection of method-parameters and roundfp-results
a61af66fc99e Initial load
duke
parents:
diff changeset
987 // TODO: move this directly to position where use-kind is computed
a61af66fc99e Initial load
duke
parents:
diff changeset
988 interval->set_spill_state(startInMemory);
a61af66fc99e Initial load
duke
parents:
diff changeset
989 }
a61af66fc99e Initial load
duke
parents:
diff changeset
990 }
a61af66fc99e Initial load
duke
parents:
diff changeset
991
a61af66fc99e Initial load
duke
parents:
diff changeset
992 void LinearScan::add_use(int reg_num, int from, int to, IntervalUseKind use_kind, BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
993 Interval* interval = interval_at(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
994 if (interval == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
995 interval = create_interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
996 }
a61af66fc99e Initial load
duke
parents:
diff changeset
997 assert(interval->reg_num() == reg_num, "wrong interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
998
a61af66fc99e Initial load
duke
parents:
diff changeset
999 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1000 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1002
a61af66fc99e Initial load
duke
parents:
diff changeset
1003 interval->add_range(from, to);
a61af66fc99e Initial load
duke
parents:
diff changeset
1004 interval->add_use_pos(to, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
1005 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1006
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 void LinearScan::add_temp(int reg_num, int temp_pos, IntervalUseKind use_kind, BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1008 Interval* interval = interval_at(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1009 if (interval == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 interval = create_interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1012 assert(interval->reg_num() == reg_num, "wrong interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1013
a61af66fc99e Initial load
duke
parents:
diff changeset
1014 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1015 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1017
a61af66fc99e Initial load
duke
parents:
diff changeset
1018 interval->add_range(temp_pos, temp_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 interval->add_use_pos(temp_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
1020 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1021
a61af66fc99e Initial load
duke
parents:
diff changeset
1022
a61af66fc99e Initial load
duke
parents:
diff changeset
1023 // the results of this functions are used for optimizing spilling and reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
1024 // if the functions return shouldHaveRegister and the interval is spilled,
a61af66fc99e Initial load
duke
parents:
diff changeset
1025 // it is not reloaded to a register.
a61af66fc99e Initial load
duke
parents:
diff changeset
1026 IntervalUseKind LinearScan::use_kind_of_output_operand(LIR_Op* op, LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1027 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1028 assert(op->as_Op1() != NULL, "lir_move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1029 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1030 LIR_Opr res = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1031 bool result_in_memory = res->is_virtual() && gen()->is_vreg_flag_set(res->vreg_number(), LIRGenerator::must_start_in_memory);
a61af66fc99e Initial load
duke
parents:
diff changeset
1032
a61af66fc99e Initial load
duke
parents:
diff changeset
1033 if (result_in_memory) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1034 // Begin of an interval with must_start_in_memory set.
a61af66fc99e Initial load
duke
parents:
diff changeset
1035 // This interval will always get a stack slot first, so return noUse.
a61af66fc99e Initial load
duke
parents:
diff changeset
1036 return noUse;
a61af66fc99e Initial load
duke
parents:
diff changeset
1037
a61af66fc99e Initial load
duke
parents:
diff changeset
1038 } else if (move->in_opr()->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1039 // method argument (condition must be equal to handle_method_arguments)
a61af66fc99e Initial load
duke
parents:
diff changeset
1040 return noUse;
a61af66fc99e Initial load
duke
parents:
diff changeset
1041
a61af66fc99e Initial load
duke
parents:
diff changeset
1042 } else if (move->in_opr()->is_register() && move->result_opr()->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1043 // Move from register to register
a61af66fc99e Initial load
duke
parents:
diff changeset
1044 if (block_of_op_with_id(op->id())->is_set(BlockBegin::osr_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1045 // special handling of phi-function moves inside osr-entry blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1046 // input operand must have a register instead of output operand (leads to better register allocation)
a61af66fc99e Initial load
duke
parents:
diff changeset
1047 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1048 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1049 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1050 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1051
a61af66fc99e Initial load
duke
parents:
diff changeset
1052 if (opr->is_virtual() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1053 gen()->is_vreg_flag_set(opr->vreg_number(), LIRGenerator::must_start_in_memory)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1054 // result is a stack-slot, so prevent immediate reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
1055 return noUse;
a61af66fc99e Initial load
duke
parents:
diff changeset
1056 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1057
a61af66fc99e Initial load
duke
parents:
diff changeset
1058 // all other operands require a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1059 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1060 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1061
a61af66fc99e Initial load
duke
parents:
diff changeset
1062 IntervalUseKind LinearScan::use_kind_of_input_operand(LIR_Op* op, LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1063 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1064 assert(op->as_Op1() != NULL, "lir_move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1065 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1066 LIR_Opr res = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1067 bool result_in_memory = res->is_virtual() && gen()->is_vreg_flag_set(res->vreg_number(), LIRGenerator::must_start_in_memory);
a61af66fc99e Initial load
duke
parents:
diff changeset
1068
a61af66fc99e Initial load
duke
parents:
diff changeset
1069 if (result_in_memory) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1070 // Move to an interval with must_start_in_memory set.
a61af66fc99e Initial load
duke
parents:
diff changeset
1071 // To avoid moves from stack to stack (not allowed) force the input operand to a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1072 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1073
a61af66fc99e Initial load
duke
parents:
diff changeset
1074 } else if (move->in_opr()->is_register() && move->result_opr()->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1075 // Move from register to register
a61af66fc99e Initial load
duke
parents:
diff changeset
1076 if (block_of_op_with_id(op->id())->is_set(BlockBegin::osr_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1077 // special handling of phi-function moves inside osr-entry blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1078 // input operand must have a register instead of output operand (leads to better register allocation)
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
a61af66fc99e Initial load
duke
parents:
diff changeset
1082 // The input operand is not forced to a register (moves from stack to register are allowed),
a61af66fc99e Initial load
duke
parents:
diff changeset
1083 // but it is faster if the input operand is in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1084 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1085 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1086 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1087
a61af66fc99e Initial load
duke
parents:
diff changeset
1088
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1089 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1090 if (op->code() == lir_cmove) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1091 // conditional moves can handle stack operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1092 assert(op->result_opr()->is_register(), "result must always be in a register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1093 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1094 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1095
a61af66fc99e Initial load
duke
parents:
diff changeset
1096 // optimizations for second input operand of arithmehtic operations on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
1097 // this operand is allowed to be on the stack in some cases
a61af66fc99e Initial load
duke
parents:
diff changeset
1098 BasicType opr_type = opr->type_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
1099 if (opr_type == T_FLOAT || opr_type == T_DOUBLE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1100 if ((UseSSE == 1 && opr_type == T_FLOAT) || UseSSE >= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1101 // SSE float instruction (T_DOUBLE only supported with SSE2)
a61af66fc99e Initial load
duke
parents:
diff changeset
1102 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1103 case lir_cmp:
a61af66fc99e Initial load
duke
parents:
diff changeset
1104 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
1105 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1106 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
1107 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
1108 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1109 assert(op->as_Op2() != NULL, "must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1110 LIR_Op2* op2 = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1111 if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1112 assert((op2->result_opr()->is_register() || op->code() == lir_cmp) && op2->in_opr1()->is_register(), "cannot mark second operand as stack if others are not in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1113 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1114 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1116 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1117 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1118 // FPU stack float instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
1119 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1120 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
1121 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1122 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
1123 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
1124 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1125 assert(op->as_Op2() != NULL, "must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1126 LIR_Op2* op2 = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1127 if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1128 assert((op2->result_opr()->is_register() || op->code() == lir_cmp) && op2->in_opr1()->is_register(), "cannot mark second operand as stack if others are not in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1129 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1130 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1131 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1132 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1133 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1134
a61af66fc99e Initial load
duke
parents:
diff changeset
1135 } else if (opr_type != T_LONG) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1136 // integer instruction (note: long operands must always be in register)
a61af66fc99e Initial load
duke
parents:
diff changeset
1137 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1138 case lir_cmp:
a61af66fc99e Initial load
duke
parents:
diff changeset
1139 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
1140 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1141 case lir_logic_and:
a61af66fc99e Initial load
duke
parents:
diff changeset
1142 case lir_logic_or:
a61af66fc99e Initial load
duke
parents:
diff changeset
1143 case lir_logic_xor:
a61af66fc99e Initial load
duke
parents:
diff changeset
1144 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1145 assert(op->as_Op2() != NULL, "must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1146 LIR_Op2* op2 = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1147 if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1148 assert((op2->result_opr()->is_register() || op->code() == lir_cmp) && op2->in_opr1()->is_register(), "cannot mark second operand as stack if others are not in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1149 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1150 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1151 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1153 }
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1154 #endif // X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1155
a61af66fc99e Initial load
duke
parents:
diff changeset
1156 // all other operands require a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1157 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1158 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1159
a61af66fc99e Initial load
duke
parents:
diff changeset
1160
a61af66fc99e Initial load
duke
parents:
diff changeset
1161 void LinearScan::handle_method_arguments(LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1162 // special handling for method arguments (moves from stack to virtual register):
a61af66fc99e Initial load
duke
parents:
diff changeset
1163 // the interval gets no register assigned, but the stack slot.
a61af66fc99e Initial load
duke
parents:
diff changeset
1164 // it is split before the first use by the register allocator.
a61af66fc99e Initial load
duke
parents:
diff changeset
1165
a61af66fc99e Initial load
duke
parents:
diff changeset
1166 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1167 assert(op->as_Op1() != NULL, "must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1168 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1169
a61af66fc99e Initial load
duke
parents:
diff changeset
1170 if (move->in_opr()->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1171 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1172 int arg_size = compilation()->method()->arg_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1173 LIR_Opr o = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1174 if (o->is_single_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1175 assert(o->single_stack_ix() >= 0 && o->single_stack_ix() < arg_size, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
1176 } else if (o->is_double_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1177 assert(o->double_stack_ix() >= 0 && o->double_stack_ix() < arg_size, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
1178 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1179 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
1180 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1181
a61af66fc99e Initial load
duke
parents:
diff changeset
1182 assert(move->id() > 0, "invalid id");
a61af66fc99e Initial load
duke
parents:
diff changeset
1183 assert(block_of_op_with_id(move->id())->number_of_preds() == 0, "move from stack must be in first block");
a61af66fc99e Initial load
duke
parents:
diff changeset
1184 assert(move->result_opr()->is_virtual(), "result of move must be a virtual register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1185
a61af66fc99e Initial load
duke
parents:
diff changeset
1186 TRACE_LINEAR_SCAN(4, tty->print_cr("found move from stack slot %d to vreg %d", o->is_single_stack() ? o->single_stack_ix() : o->double_stack_ix(), reg_num(move->result_opr())));
a61af66fc99e Initial load
duke
parents:
diff changeset
1187 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1188
a61af66fc99e Initial load
duke
parents:
diff changeset
1189 Interval* interval = interval_at(reg_num(move->result_opr()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1190
a61af66fc99e Initial load
duke
parents:
diff changeset
1191 int stack_slot = LinearScan::nof_regs + (move->in_opr()->is_single_stack() ? move->in_opr()->single_stack_ix() : move->in_opr()->double_stack_ix());
a61af66fc99e Initial load
duke
parents:
diff changeset
1192 interval->set_canonical_spill_slot(stack_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
1193 interval->assign_reg(stack_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
1194 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1195 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1197
a61af66fc99e Initial load
duke
parents:
diff changeset
1198 void LinearScan::handle_doubleword_moves(LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1199 // special handling for doubleword move from memory to register:
a61af66fc99e Initial load
duke
parents:
diff changeset
1200 // in this case the registers of the input address and the result
a61af66fc99e Initial load
duke
parents:
diff changeset
1201 // registers must not overlap -> add a temp range for the input registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1202 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1203 assert(op->as_Op1() != NULL, "must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1204 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1205
a61af66fc99e Initial load
duke
parents:
diff changeset
1206 if (move->result_opr()->is_double_cpu() && move->in_opr()->is_pointer()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1207 LIR_Address* address = move->in_opr()->as_address_ptr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1208 if (address != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1209 if (address->base()->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1210 add_temp(address->base(), op->id(), noUse);
a61af66fc99e Initial load
duke
parents:
diff changeset
1211 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1212 if (address->index()->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1213 add_temp(address->index(), op->id(), noUse);
a61af66fc99e Initial load
duke
parents:
diff changeset
1214 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1215 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1217 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1218 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1219
a61af66fc99e Initial load
duke
parents:
diff changeset
1220 void LinearScan::add_register_hints(LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1221 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1222 case lir_move: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
1223 case lir_convert: {
a61af66fc99e Initial load
duke
parents:
diff changeset
1224 assert(op->as_Op1() != NULL, "lir_move, lir_convert must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1225 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1226
a61af66fc99e Initial load
duke
parents:
diff changeset
1227 LIR_Opr move_from = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1228 LIR_Opr move_to = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1229
a61af66fc99e Initial load
duke
parents:
diff changeset
1230 if (move_to->is_register() && move_from->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1231 Interval* from = interval_at(reg_num(move_from));
a61af66fc99e Initial load
duke
parents:
diff changeset
1232 Interval* to = interval_at(reg_num(move_to));
a61af66fc99e Initial load
duke
parents:
diff changeset
1233 if (from != NULL && to != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1234 to->set_register_hint(from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1235 TRACE_LINEAR_SCAN(4, tty->print_cr("operation at op_id %d: added hint from interval %d to %d", move->id(), from->reg_num(), to->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1237 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1238 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1239 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1240 case lir_cmove: {
a61af66fc99e Initial load
duke
parents:
diff changeset
1241 assert(op->as_Op2() != NULL, "lir_cmove must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1242 LIR_Op2* cmove = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1243
a61af66fc99e Initial load
duke
parents:
diff changeset
1244 LIR_Opr move_from = cmove->in_opr1();
a61af66fc99e Initial load
duke
parents:
diff changeset
1245 LIR_Opr move_to = cmove->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1246
a61af66fc99e Initial load
duke
parents:
diff changeset
1247 if (move_to->is_register() && move_from->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1248 Interval* from = interval_at(reg_num(move_from));
a61af66fc99e Initial load
duke
parents:
diff changeset
1249 Interval* to = interval_at(reg_num(move_to));
a61af66fc99e Initial load
duke
parents:
diff changeset
1250 if (from != NULL && to != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1251 to->set_register_hint(from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1252 TRACE_LINEAR_SCAN(4, tty->print_cr("operation at op_id %d: added hint from interval %d to %d", cmove->id(), from->reg_num(), to->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1253 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1254 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1255 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1256 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1258 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1259
a61af66fc99e Initial load
duke
parents:
diff changeset
1260
a61af66fc99e Initial load
duke
parents:
diff changeset
1261 void LinearScan::build_intervals() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1262 TIME_LINEAR_SCAN(timer_build_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1263
a61af66fc99e Initial load
duke
parents:
diff changeset
1264 // initialize interval list with expected number of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1265 // (32 is added to have some space for split children without having to resize the list)
a61af66fc99e Initial load
duke
parents:
diff changeset
1266 _intervals = IntervalList(num_virtual_regs() + 32);
a61af66fc99e Initial load
duke
parents:
diff changeset
1267 // initialize all slots that are used by build_intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1268 _intervals.at_put_grow(num_virtual_regs() - 1, NULL, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1269
a61af66fc99e Initial load
duke
parents:
diff changeset
1270 // create a list with all caller-save registers (cpu, fpu, xmm)
a61af66fc99e Initial load
duke
parents:
diff changeset
1271 // when an instruction is a call, a temp range is created for all these registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1272 int num_caller_save_registers = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1273 int caller_save_registers[LinearScan::nof_regs];
a61af66fc99e Initial load
duke
parents:
diff changeset
1274
a61af66fc99e Initial load
duke
parents:
diff changeset
1275 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1276 for (i = 0; i < FrameMap::nof_caller_save_cpu_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1277 LIR_Opr opr = FrameMap::caller_save_cpu_reg_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1278 assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1279 assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1280 caller_save_registers[num_caller_save_registers++] = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1281 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1282
a61af66fc99e Initial load
duke
parents:
diff changeset
1283 // temp ranges for fpu registers are only created when the method has
a61af66fc99e Initial load
duke
parents:
diff changeset
1284 // virtual fpu operands. Otherwise no allocation for fpu registers is
a61af66fc99e Initial load
duke
parents:
diff changeset
1285 // perfomed and so the temp ranges would be useless
a61af66fc99e Initial load
duke
parents:
diff changeset
1286 if (has_fpu_registers()) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1287 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1288 if (UseSSE < 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1289 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1290 for (i = 0; i < FrameMap::nof_caller_save_fpu_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1291 LIR_Opr opr = FrameMap::caller_save_fpu_reg_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1292 assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1293 assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1294 caller_save_registers[num_caller_save_registers++] = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1295 }
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1296 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1297 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1298 if (UseSSE > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1299 for (i = 0; i < FrameMap::nof_caller_save_xmm_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1300 LIR_Opr opr = FrameMap::caller_save_xmm_reg_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1301 assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1302 assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1303 caller_save_registers[num_caller_save_registers++] = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1304 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1305 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1306 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1307 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1308 assert(num_caller_save_registers <= LinearScan::nof_regs, "out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1309
a61af66fc99e Initial load
duke
parents:
diff changeset
1310
a61af66fc99e Initial load
duke
parents:
diff changeset
1311 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
1312
a61af66fc99e Initial load
duke
parents:
diff changeset
1313 // iterate all blocks in reverse order
a61af66fc99e Initial load
duke
parents:
diff changeset
1314 for (i = block_count() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1315 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1316 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1317 int block_from = block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1318 int block_to = block->last_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1319
a61af66fc99e Initial load
duke
parents:
diff changeset
1320 assert(block_from == instructions->at(0)->id(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
1321 assert(block_to == instructions->at(instructions->length() - 1)->id(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
1322
a61af66fc99e Initial load
duke
parents:
diff changeset
1323 // Update intervals for registers live at the end of this block;
a61af66fc99e Initial load
duke
parents:
diff changeset
1324 BitMap live = block->live_out();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1325 int size = (int)live.size();
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1326 for (int number = (int)live.get_next_one_offset(0, size); number < size; number = (int)live.get_next_one_offset(number + 1, size)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1327 assert(live.at(number), "should not stop here otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1328 assert(number >= LIR_OprDesc::vreg_base, "fixed intervals must not be live on block bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1329 TRACE_LINEAR_SCAN(2, tty->print_cr("live in %d to %d", number, block_to + 2));
a61af66fc99e Initial load
duke
parents:
diff changeset
1330
a61af66fc99e Initial load
duke
parents:
diff changeset
1331 add_use(number, block_from, block_to + 2, noUse, T_ILLEGAL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1332
a61af66fc99e Initial load
duke
parents:
diff changeset
1333 // add special use positions for loop-end blocks when the
a61af66fc99e Initial load
duke
parents:
diff changeset
1334 // interval is used anywhere inside this loop. It's possible
a61af66fc99e Initial load
duke
parents:
diff changeset
1335 // that the block was part of a non-natural loop, so it might
a61af66fc99e Initial load
duke
parents:
diff changeset
1336 // have an invalid loop index.
a61af66fc99e Initial load
duke
parents:
diff changeset
1337 if (block->is_set(BlockBegin::linear_scan_loop_end_flag) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1338 block->loop_index() != -1 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1339 is_interval_in_loop(number, block->loop_index())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1340 interval_at(number)->add_use_pos(block_to + 1, loopEndMarker);
a61af66fc99e Initial load
duke
parents:
diff changeset
1341 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1342 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1343
a61af66fc99e Initial load
duke
parents:
diff changeset
1344 // iterate all instructions of the block in reverse order.
a61af66fc99e Initial load
duke
parents:
diff changeset
1345 // skip the first instruction because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
1346 // definitions of intervals are processed before uses
a61af66fc99e Initial load
duke
parents:
diff changeset
1347 assert(visitor.no_operands(instructions->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1348 for (int j = instructions->length() - 1; j >= 1; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1349 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
1350 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1351
a61af66fc99e Initial load
duke
parents:
diff changeset
1352 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1353 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1354
a61af66fc99e Initial load
duke
parents:
diff changeset
1355 // add a temp range for each register if operation destroys caller-save registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1356 if (visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1357 for (int k = 0; k < num_caller_save_registers; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1358 add_temp(caller_save_registers[k], op_id, noUse, T_ILLEGAL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1359 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1360 TRACE_LINEAR_SCAN(4, tty->print_cr("operation destroys all caller-save registers"));
a61af66fc99e Initial load
duke
parents:
diff changeset
1361 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1362
a61af66fc99e Initial load
duke
parents:
diff changeset
1363 // Add any platform dependent temps
a61af66fc99e Initial load
duke
parents:
diff changeset
1364 pd_add_temps(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1365
a61af66fc99e Initial load
duke
parents:
diff changeset
1366 // visit definitions (output and temp operands)
a61af66fc99e Initial load
duke
parents:
diff changeset
1367 int k, n;
a61af66fc99e Initial load
duke
parents:
diff changeset
1368 n = visitor.opr_count(LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1369 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1370 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1371 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1372 add_def(opr, op_id, use_kind_of_output_operand(op, opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
1373 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1374
a61af66fc99e Initial load
duke
parents:
diff changeset
1375 n = visitor.opr_count(LIR_OpVisitState::tempMode);
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::tempMode, 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_temp(opr, op_id, mustHaveRegister);
a61af66fc99e Initial load
duke
parents:
diff changeset
1380 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1381
a61af66fc99e Initial load
duke
parents:
diff changeset
1382 // visit uses (input operands)
a61af66fc99e Initial load
duke
parents:
diff changeset
1383 n = visitor.opr_count(LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1384 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1385 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1386 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1387 add_use(opr, block_from, op_id, use_kind_of_input_operand(op, opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
1388 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1389
a61af66fc99e Initial load
duke
parents:
diff changeset
1390 // Add uses of live locals from interpreter's point of view for proper
a61af66fc99e Initial load
duke
parents:
diff changeset
1391 // debug information generation
a61af66fc99e Initial load
duke
parents:
diff changeset
1392 // Treat these operands as temp values (if the life range is extended
a61af66fc99e Initial load
duke
parents:
diff changeset
1393 // to a call site, the value would be in a register at the call otherwise)
a61af66fc99e Initial load
duke
parents:
diff changeset
1394 n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1395 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1396 CodeEmitInfo* info = visitor.info_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1397 ValueStack* stack = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
1398 for_each_state_value(stack, value,
a61af66fc99e Initial load
duke
parents:
diff changeset
1399 add_use(value, block_from, op_id + 1, noUse);
a61af66fc99e Initial load
duke
parents:
diff changeset
1400 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1401 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1402
a61af66fc99e Initial load
duke
parents:
diff changeset
1403 // special steps for some instructions (especially moves)
a61af66fc99e Initial load
duke
parents:
diff changeset
1404 handle_method_arguments(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1405 handle_doubleword_moves(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1406 add_register_hints(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1407
a61af66fc99e Initial load
duke
parents:
diff changeset
1408 } // end of instruction iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
1409 } // end of block iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
1410
a61af66fc99e Initial load
duke
parents:
diff changeset
1411
a61af66fc99e Initial load
duke
parents:
diff changeset
1412 // add the range [0, 1[ to all fixed intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1413 // -> the register allocator need not handle unhandled fixed intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1414 for (int n = 0; n < LinearScan::nof_regs; n++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1415 Interval* interval = interval_at(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
1416 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1417 interval->add_range(0, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1418 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1419 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1420 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1421
a61af66fc99e Initial load
duke
parents:
diff changeset
1422
a61af66fc99e Initial load
duke
parents:
diff changeset
1423 // ********** Phase 5: actual register allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
1424
a61af66fc99e Initial load
duke
parents:
diff changeset
1425 int LinearScan::interval_cmp(Interval** a, Interval** b) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1426 if (*a != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1427 if (*b != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1428 return (*a)->from() - (*b)->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1429 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1430 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1431 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1432 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1433 if (*b != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1434 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1435 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1436 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1437 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1438 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1439 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1440
a61af66fc99e Initial load
duke
parents:
diff changeset
1441 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1442 bool LinearScan::is_sorted(IntervalArray* intervals) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1443 int from = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1444 int i, j;
a61af66fc99e Initial load
duke
parents:
diff changeset
1445 for (i = 0; i < intervals->length(); i ++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1446 Interval* it = intervals->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1447 if (it != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1448 if (from > it->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1449 assert(false, "");
a61af66fc99e Initial load
duke
parents:
diff changeset
1450 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
1451 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1452 from = it->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1453 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1454 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1455
a61af66fc99e Initial load
duke
parents:
diff changeset
1456 // check in both directions if sorted list and unsorted list contain same intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1457 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1458 if (interval_at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1459 int num_found = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1460 for (j = 0; j < intervals->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1461 if (interval_at(i) == intervals->at(j)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1462 num_found++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1463 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1464 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1465 assert(num_found == 1, "lists do not contain same intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
1466 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1467 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1468 for (j = 0; j < intervals->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1469 int num_found = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1470 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1471 if (interval_at(i) == intervals->at(j)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1472 num_found++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1474 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1475 assert(num_found == 1, "lists do not contain same intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
1476 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1477
a61af66fc99e Initial load
duke
parents:
diff changeset
1478 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1479 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1480 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1481
a61af66fc99e Initial load
duke
parents:
diff changeset
1482 void LinearScan::add_to_list(Interval** first, Interval** prev, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1483 if (*prev != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1484 (*prev)->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1485 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1486 *first = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1488 *prev = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1490
a61af66fc99e Initial load
duke
parents:
diff changeset
1491 void LinearScan::create_unhandled_lists(Interval** list1, Interval** list2, bool (is_list1)(const Interval* i), bool (is_list2)(const Interval* i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1492 assert(is_sorted(_sorted_intervals), "interval list is not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
1493
a61af66fc99e Initial load
duke
parents:
diff changeset
1494 *list1 = *list2 = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
1495
a61af66fc99e Initial load
duke
parents:
diff changeset
1496 Interval* list1_prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1497 Interval* list2_prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1498 Interval* v;
a61af66fc99e Initial load
duke
parents:
diff changeset
1499
a61af66fc99e Initial load
duke
parents:
diff changeset
1500 const int n = _sorted_intervals->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1501 for (int i = 0; i < n; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1502 v = _sorted_intervals->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1503 if (v == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
1504
a61af66fc99e Initial load
duke
parents:
diff changeset
1505 if (is_list1(v)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1506 add_to_list(list1, &list1_prev, v);
a61af66fc99e Initial load
duke
parents:
diff changeset
1507 } else if (is_list2 == NULL || is_list2(v)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1508 add_to_list(list2, &list2_prev, v);
a61af66fc99e Initial load
duke
parents:
diff changeset
1509 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1510 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1511
a61af66fc99e Initial load
duke
parents:
diff changeset
1512 if (list1_prev != NULL) list1_prev->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
1513 if (list2_prev != NULL) list2_prev->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
1514
a61af66fc99e Initial load
duke
parents:
diff changeset
1515 assert(list1_prev == NULL || list1_prev->next() == Interval::end(), "linear list ends not with sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
1516 assert(list2_prev == NULL || list2_prev->next() == Interval::end(), "linear list ends not with sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
1517 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1518
a61af66fc99e Initial load
duke
parents:
diff changeset
1519
a61af66fc99e Initial load
duke
parents:
diff changeset
1520 void LinearScan::sort_intervals_before_allocation() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1521 TIME_LINEAR_SCAN(timer_sort_intervals_before);
a61af66fc99e Initial load
duke
parents:
diff changeset
1522
a61af66fc99e Initial load
duke
parents:
diff changeset
1523 IntervalList* unsorted_list = &_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1524 int unsorted_len = unsorted_list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1525 int sorted_len = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1526 int unsorted_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
1527 int sorted_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1528 int sorted_from_max = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1529
a61af66fc99e Initial load
duke
parents:
diff changeset
1530 // calc number of items for sorted list (sorted list must not contain NULL values)
a61af66fc99e Initial load
duke
parents:
diff changeset
1531 for (unsorted_idx = 0; unsorted_idx < unsorted_len; unsorted_idx++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1532 if (unsorted_list->at(unsorted_idx) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1533 sorted_len++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1534 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1535 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1536 IntervalArray* sorted_list = new IntervalArray(sorted_len);
a61af66fc99e Initial load
duke
parents:
diff changeset
1537
a61af66fc99e Initial load
duke
parents:
diff changeset
1538 // special sorting algorithm: the original interval-list is almost sorted,
a61af66fc99e Initial load
duke
parents:
diff changeset
1539 // only some intervals are swapped. So this is much faster than a complete QuickSort
a61af66fc99e Initial load
duke
parents:
diff changeset
1540 for (unsorted_idx = 0; unsorted_idx < unsorted_len; unsorted_idx++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1541 Interval* cur_interval = unsorted_list->at(unsorted_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
1542
a61af66fc99e Initial load
duke
parents:
diff changeset
1543 if (cur_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1544 int cur_from = cur_interval->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1545
a61af66fc99e Initial load
duke
parents:
diff changeset
1546 if (sorted_from_max <= cur_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1547 sorted_list->at_put(sorted_idx++, cur_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1548 sorted_from_max = cur_interval->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1549 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1550 // the asumption that the intervals are already sorted failed,
a61af66fc99e Initial load
duke
parents:
diff changeset
1551 // so this interval must be sorted in manually
a61af66fc99e Initial load
duke
parents:
diff changeset
1552 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
1553 for (j = sorted_idx - 1; j >= 0 && cur_from < sorted_list->at(j)->from(); j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1554 sorted_list->at_put(j + 1, sorted_list->at(j));
a61af66fc99e Initial load
duke
parents:
diff changeset
1555 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1556 sorted_list->at_put(j + 1, cur_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1557 sorted_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1558 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1559 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1560 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1561 _sorted_intervals = sorted_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
1562 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1563
a61af66fc99e Initial load
duke
parents:
diff changeset
1564 void LinearScan::sort_intervals_after_allocation() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1565 TIME_LINEAR_SCAN(timer_sort_intervals_after);
a61af66fc99e Initial load
duke
parents:
diff changeset
1566
a61af66fc99e Initial load
duke
parents:
diff changeset
1567 IntervalArray* old_list = _sorted_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1568 IntervalList* new_list = _new_intervals_from_allocation;
a61af66fc99e Initial load
duke
parents:
diff changeset
1569 int old_len = old_list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1570 int new_len = new_list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1571
a61af66fc99e Initial load
duke
parents:
diff changeset
1572 if (new_len == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1573 // no intervals have been added during allocation, so sorted list is already up to date
a61af66fc99e Initial load
duke
parents:
diff changeset
1574 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1575 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1576
a61af66fc99e Initial load
duke
parents:
diff changeset
1577 // conventional sort-algorithm for new intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1578 new_list->sort(interval_cmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
1579
a61af66fc99e Initial load
duke
parents:
diff changeset
1580 // merge old and new list (both already sorted) into one combined list
a61af66fc99e Initial load
duke
parents:
diff changeset
1581 IntervalArray* combined_list = new IntervalArray(old_len + new_len);
a61af66fc99e Initial load
duke
parents:
diff changeset
1582 int old_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1583 int new_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1584
a61af66fc99e Initial load
duke
parents:
diff changeset
1585 while (old_idx + new_idx < old_len + new_len) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1586 if (new_idx >= new_len || (old_idx < old_len && old_list->at(old_idx)->from() <= new_list->at(new_idx)->from())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1587 combined_list->at_put(old_idx + new_idx, old_list->at(old_idx));
a61af66fc99e Initial load
duke
parents:
diff changeset
1588 old_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1589 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1590 combined_list->at_put(old_idx + new_idx, new_list->at(new_idx));
a61af66fc99e Initial load
duke
parents:
diff changeset
1591 new_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1592 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1593 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1594
a61af66fc99e Initial load
duke
parents:
diff changeset
1595 _sorted_intervals = combined_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
1596 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1597
a61af66fc99e Initial load
duke
parents:
diff changeset
1598
a61af66fc99e Initial load
duke
parents:
diff changeset
1599 void LinearScan::allocate_registers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1600 TIME_LINEAR_SCAN(timer_allocate_registers);
a61af66fc99e Initial load
duke
parents:
diff changeset
1601
a61af66fc99e Initial load
duke
parents:
diff changeset
1602 Interval* precolored_cpu_intervals, *not_precolored_cpu_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1603 Interval* precolored_fpu_intervals, *not_precolored_fpu_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1604
a61af66fc99e Initial load
duke
parents:
diff changeset
1605 create_unhandled_lists(&precolored_cpu_intervals, &not_precolored_cpu_intervals, is_precolored_cpu_interval, is_virtual_cpu_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1606 if (has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1607 create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1608 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1609 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1610 // fpu register allocation is omitted because no virtual fpu registers are present
a61af66fc99e Initial load
duke
parents:
diff changeset
1611 // just check this again...
a61af66fc99e Initial load
duke
parents:
diff changeset
1612 create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1613 assert(not_precolored_fpu_intervals == Interval::end(), "missed an uncolored fpu interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1614 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1615 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1616
a61af66fc99e Initial load
duke
parents:
diff changeset
1617 // allocate cpu registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1618 LinearScanWalker cpu_lsw(this, precolored_cpu_intervals, not_precolored_cpu_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1619 cpu_lsw.walk();
a61af66fc99e Initial load
duke
parents:
diff changeset
1620 cpu_lsw.finish_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
1621
a61af66fc99e Initial load
duke
parents:
diff changeset
1622 if (has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1623 // allocate fpu registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1624 LinearScanWalker fpu_lsw(this, precolored_fpu_intervals, not_precolored_fpu_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1625 fpu_lsw.walk();
a61af66fc99e Initial load
duke
parents:
diff changeset
1626 fpu_lsw.finish_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
1627 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1628 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1629
a61af66fc99e Initial load
duke
parents:
diff changeset
1630
a61af66fc99e Initial load
duke
parents:
diff changeset
1631 // ********** Phase 6: resolve data flow
a61af66fc99e Initial load
duke
parents:
diff changeset
1632 // (insert moves at edges between blocks if intervals have been split)
a61af66fc99e Initial load
duke
parents:
diff changeset
1633
a61af66fc99e Initial load
duke
parents:
diff changeset
1634 // wrapper for Interval::split_child_at_op_id that performs a bailout in product mode
a61af66fc99e Initial load
duke
parents:
diff changeset
1635 // instead of returning NULL
a61af66fc99e Initial load
duke
parents:
diff changeset
1636 Interval* LinearScan::split_child_at_op_id(Interval* interval, int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1637 Interval* result = interval->split_child_at_op_id(op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1638 if (result != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1639 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
1640 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1641
a61af66fc99e Initial load
duke
parents:
diff changeset
1642 assert(false, "must find an interval, but do a clean bailout in product mode");
a61af66fc99e Initial load
duke
parents:
diff changeset
1643 result = new Interval(LIR_OprDesc::vreg_base);
a61af66fc99e Initial load
duke
parents:
diff changeset
1644 result->assign_reg(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1645 result->set_type(T_INT);
a61af66fc99e Initial load
duke
parents:
diff changeset
1646 BAILOUT_("LinearScan: interval is NULL", result);
a61af66fc99e Initial load
duke
parents:
diff changeset
1647 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1648
a61af66fc99e Initial load
duke
parents:
diff changeset
1649
a61af66fc99e Initial load
duke
parents:
diff changeset
1650 Interval* LinearScan::interval_at_block_begin(BlockBegin* block, int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1651 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1652 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1653
a61af66fc99e Initial load
duke
parents:
diff changeset
1654 return split_child_at_op_id(interval_at(reg_num), block->first_lir_instruction_id(), LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1655 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1656
a61af66fc99e Initial load
duke
parents:
diff changeset
1657 Interval* LinearScan::interval_at_block_end(BlockBegin* block, int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1658 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1659 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1660
a61af66fc99e Initial load
duke
parents:
diff changeset
1661 return split_child_at_op_id(interval_at(reg_num), block->last_lir_instruction_id() + 1, LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1662 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1663
a61af66fc99e Initial load
duke
parents:
diff changeset
1664 Interval* LinearScan::interval_at_op_id(int reg_num, int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1665 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1666 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1667
a61af66fc99e Initial load
duke
parents:
diff changeset
1668 return split_child_at_op_id(interval_at(reg_num), op_id, LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1669 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1670
a61af66fc99e Initial load
duke
parents:
diff changeset
1671
a61af66fc99e Initial load
duke
parents:
diff changeset
1672 void LinearScan::resolve_collect_mappings(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1673 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1674
a61af66fc99e Initial load
duke
parents:
diff changeset
1675 const int num_regs = num_virtual_regs();
a61af66fc99e Initial load
duke
parents:
diff changeset
1676 const int size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1677 const BitMap live_at_edge = to_block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
1678
a61af66fc99e Initial load
duke
parents:
diff changeset
1679 // 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
1680 for (int r = (int)live_at_edge.get_next_one_offset(0, size); r < size; r = (int)live_at_edge.get_next_one_offset(r + 1, size)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1681 assert(r < num_regs, "live information set for not exisiting interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1682 assert(from_block->live_out().at(r) && to_block->live_in().at(r), "interval not live at this edge");
a61af66fc99e Initial load
duke
parents:
diff changeset
1683
a61af66fc99e Initial load
duke
parents:
diff changeset
1684 Interval* from_interval = interval_at_block_end(from_block, r);
a61af66fc99e Initial load
duke
parents:
diff changeset
1685 Interval* to_interval = interval_at_block_begin(to_block, r);
a61af66fc99e Initial load
duke
parents:
diff changeset
1686
a61af66fc99e Initial load
duke
parents:
diff changeset
1687 if (from_interval != to_interval && (from_interval->assigned_reg() != to_interval->assigned_reg() || from_interval->assigned_regHi() != to_interval->assigned_regHi())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1688 // need to insert move instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
1689 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1690 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1691 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1692 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1693
a61af66fc99e Initial load
duke
parents:
diff changeset
1694
a61af66fc99e Initial load
duke
parents:
diff changeset
1695 void LinearScan::resolve_find_insert_pos(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1696 if (from_block->number_of_sux() <= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1697 TRACE_LINEAR_SCAN(4, tty->print_cr("inserting moves at end of from_block B%d", from_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1698
a61af66fc99e Initial load
duke
parents:
diff changeset
1699 LIR_OpList* instructions = from_block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1700 LIR_OpBranch* branch = instructions->last()->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
1701 if (branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1702 // insert moves before branch
a61af66fc99e Initial load
duke
parents:
diff changeset
1703 assert(branch->cond() == lir_cond_always, "block does not end with an unconditional jump");
a61af66fc99e Initial load
duke
parents:
diff changeset
1704 move_resolver.set_insert_position(from_block->lir(), instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1705 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1706 move_resolver.set_insert_position(from_block->lir(), instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1707 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1708
a61af66fc99e Initial load
duke
parents:
diff changeset
1709 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1710 TRACE_LINEAR_SCAN(4, tty->print_cr("inserting moves at beginning of to_block B%d", to_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1711 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1712 assert(from_block->lir()->instructions_list()->at(0)->as_OpLabel() != NULL, "block does not start with a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1713
a61af66fc99e Initial load
duke
parents:
diff changeset
1714 // because the number of predecessor edges matches the number of
a61af66fc99e Initial load
duke
parents:
diff changeset
1715 // successor edges, blocks which are reached by switch statements
a61af66fc99e Initial load
duke
parents:
diff changeset
1716 // may have be more than one predecessor but it will be guaranteed
a61af66fc99e Initial load
duke
parents:
diff changeset
1717 // that all predecessors will be the same.
a61af66fc99e Initial load
duke
parents:
diff changeset
1718 for (int i = 0; i < to_block->number_of_preds(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1719 assert(from_block == to_block->pred_at(i), "all critical edges must be broken");
a61af66fc99e Initial load
duke
parents:
diff changeset
1720 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1721 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1722
a61af66fc99e Initial load
duke
parents:
diff changeset
1723 move_resolver.set_insert_position(to_block->lir(), 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1724 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1725 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1726
a61af66fc99e Initial load
duke
parents:
diff changeset
1727
a61af66fc99e Initial load
duke
parents:
diff changeset
1728 // insert necessary moves (spilling or reloading) at edges between blocks if interval has been split
a61af66fc99e Initial load
duke
parents:
diff changeset
1729 void LinearScan::resolve_data_flow() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1730 TIME_LINEAR_SCAN(timer_resolve_data_flow);
a61af66fc99e Initial load
duke
parents:
diff changeset
1731
a61af66fc99e Initial load
duke
parents:
diff changeset
1732 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1733 MoveResolver move_resolver(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
1734 BitMap block_completed(num_blocks); block_completed.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
1735 BitMap already_resolved(num_blocks); already_resolved.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
1736
a61af66fc99e Initial load
duke
parents:
diff changeset
1737 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1738 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1739 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1740
a61af66fc99e Initial load
duke
parents:
diff changeset
1741 // check if block has only one predecessor and only one successor
a61af66fc99e Initial load
duke
parents:
diff changeset
1742 if (block->number_of_preds() == 1 && block->number_of_sux() == 1 && block->number_of_exception_handlers() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1743 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1744 assert(instructions->at(0)->code() == lir_label, "block must start with label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1745 assert(instructions->last()->code() == lir_branch, "block with successors must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
1746 assert(instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block with successor must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
1747
a61af66fc99e Initial load
duke
parents:
diff changeset
1748 // check if block is empty (only label and branch)
a61af66fc99e Initial load
duke
parents:
diff changeset
1749 if (instructions->length() == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1750 BlockBegin* pred = block->pred_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1751 BlockBegin* sux = block->sux_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1752
a61af66fc99e Initial load
duke
parents:
diff changeset
1753 // prevent optimization of two consecutive blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1754 if (!block_completed.at(pred->linear_scan_number()) && !block_completed.at(sux->linear_scan_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1755 TRACE_LINEAR_SCAN(3, tty->print_cr("**** optimizing empty block B%d (pred: B%d, sux: B%d)", block->block_id(), pred->block_id(), sux->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1756 block_completed.set_bit(block->linear_scan_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
1757
a61af66fc99e Initial load
duke
parents:
diff changeset
1758 // directly resolve between pred and sux (without looking at the empty block between)
a61af66fc99e Initial load
duke
parents:
diff changeset
1759 resolve_collect_mappings(pred, sux, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1760 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1761 move_resolver.set_insert_position(block->lir(), 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1762 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1763 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1764 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1765 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1766 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1767 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1768
a61af66fc99e Initial load
duke
parents:
diff changeset
1769
a61af66fc99e Initial load
duke
parents:
diff changeset
1770 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1771 if (!block_completed.at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1772 BlockBegin* from_block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1773 already_resolved.set_from(block_completed);
a61af66fc99e Initial load
duke
parents:
diff changeset
1774
a61af66fc99e Initial load
duke
parents:
diff changeset
1775 int num_sux = from_block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
1776 for (int s = 0; s < num_sux; s++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1777 BlockBegin* to_block = from_block->sux_at(s);
a61af66fc99e Initial load
duke
parents:
diff changeset
1778
a61af66fc99e Initial load
duke
parents:
diff changeset
1779 // check for duplicate edges between the same blocks (can happen with switch blocks)
a61af66fc99e Initial load
duke
parents:
diff changeset
1780 if (!already_resolved.at(to_block->linear_scan_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1781 TRACE_LINEAR_SCAN(3, tty->print_cr("**** processing edge between B%d and B%d", from_block->block_id(), to_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1782 already_resolved.set_bit(to_block->linear_scan_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
1783
a61af66fc99e Initial load
duke
parents:
diff changeset
1784 // collect all intervals that have been split between from_block and to_block
a61af66fc99e Initial load
duke
parents:
diff changeset
1785 resolve_collect_mappings(from_block, to_block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1786 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1787 resolve_find_insert_pos(from_block, to_block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1788 move_resolver.resolve_and_append_moves();
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 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1795
a61af66fc99e Initial load
duke
parents:
diff changeset
1796
a61af66fc99e Initial load
duke
parents:
diff changeset
1797 void LinearScan::resolve_exception_entry(BlockBegin* block, int reg_num, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1798 if (interval_at(reg_num) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1799 // if a phi function is never used, no interval is created -> ignore this
a61af66fc99e Initial load
duke
parents:
diff changeset
1800 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1801 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1802
a61af66fc99e Initial load
duke
parents:
diff changeset
1803 Interval* interval = interval_at_block_begin(block, reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1804 int reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
1805 int regHi = interval->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
1806
a61af66fc99e Initial load
duke
parents:
diff changeset
1807 if ((reg < nof_regs && interval->always_in_memory()) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
1808 (use_fpu_stack_allocation() && reg >= pd_first_fpu_reg && reg <= pd_last_fpu_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1809 // the interval is split to get a short range that is located on the stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1810 // in the following two cases:
a61af66fc99e Initial load
duke
parents:
diff changeset
1811 // * the interval started in memory (e.g. method parameter), but is currently in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1812 // this is an optimization for exception handling that reduces the number of moves that
a61af66fc99e Initial load
duke
parents:
diff changeset
1813 // are necessary for resolving the states when an exception uses this exception handler
a61af66fc99e Initial load
duke
parents:
diff changeset
1814 // * the interval would be on the fpu stack at the begin of the exception handler
a61af66fc99e Initial load
duke
parents:
diff changeset
1815 // this is not allowed because of the complicated fpu stack handling on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
1816
a61af66fc99e Initial load
duke
parents:
diff changeset
1817 // range that will be spilled to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
1818 int from_op_id = block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1819 int to_op_id = from_op_id + 1; // short live range of length 1
a61af66fc99e Initial load
duke
parents:
diff changeset
1820 assert(interval->from() <= from_op_id && interval->to() >= to_op_id,
a61af66fc99e Initial load
duke
parents:
diff changeset
1821 "no split allowed between exception entry and first instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
1822
a61af66fc99e Initial load
duke
parents:
diff changeset
1823 if (interval->from() != from_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1824 // the part before from_op_id is unchanged
a61af66fc99e Initial load
duke
parents:
diff changeset
1825 interval = interval->split(from_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1826 interval->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
1827 append_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1828 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1829 assert(interval->from() == from_op_id, "must be true now");
a61af66fc99e Initial load
duke
parents:
diff changeset
1830
a61af66fc99e Initial load
duke
parents:
diff changeset
1831 Interval* spilled_part = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1832 if (interval->to() != to_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1833 // the part after to_op_id is unchanged
a61af66fc99e Initial load
duke
parents:
diff changeset
1834 spilled_part = interval->split_from_start(to_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1835 append_interval(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
1836 move_resolver.add_mapping(spilled_part, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1837 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1838 assign_spill_slot(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
1839
a61af66fc99e Initial load
duke
parents:
diff changeset
1840 assert(spilled_part->from() == from_op_id && spilled_part->to() == to_op_id, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
1841 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1842 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1843
a61af66fc99e Initial load
duke
parents:
diff changeset
1844 void LinearScan::resolve_exception_entry(BlockBegin* block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1845 assert(block->is_set(BlockBegin::exception_entry_flag), "should not call otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1846 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1847
a61af66fc99e Initial load
duke
parents:
diff changeset
1848 // visit all registers where the live_in bit is set
a61af66fc99e Initial load
duke
parents:
diff changeset
1849 int size = live_set_size();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1850 for (int r = (int)block->live_in().get_next_one_offset(0, size); r < size; r = (int)block->live_in().get_next_one_offset(r + 1, size)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1851 resolve_exception_entry(block, r, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1852 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1853
a61af66fc99e Initial load
duke
parents:
diff changeset
1854 // the live_in bits are not set for phi functions of the xhandler entry, so iterate them separately
a61af66fc99e Initial load
duke
parents:
diff changeset
1855 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
1856 resolve_exception_entry(block, phi->operand()->vreg_number(), move_resolver)
a61af66fc99e Initial load
duke
parents:
diff changeset
1857 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1858
a61af66fc99e Initial load
duke
parents:
diff changeset
1859 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1860 // insert moves after first instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
1861 move_resolver.set_insert_position(block->lir(), 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1862 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1863 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1864 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1865
a61af66fc99e Initial load
duke
parents:
diff changeset
1866
a61af66fc99e Initial load
duke
parents:
diff changeset
1867 void LinearScan::resolve_exception_edge(XHandler* handler, int throwing_op_id, int reg_num, Phi* phi, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1868 if (interval_at(reg_num) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1869 // if a phi function is never used, no interval is created -> ignore this
a61af66fc99e Initial load
duke
parents:
diff changeset
1870 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1871 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1872
a61af66fc99e Initial load
duke
parents:
diff changeset
1873 // the computation of to_interval is equal to resolve_collect_mappings,
a61af66fc99e Initial load
duke
parents:
diff changeset
1874 // but from_interval is more complicated because of phi functions
a61af66fc99e Initial load
duke
parents:
diff changeset
1875 BlockBegin* to_block = handler->entry_block();
a61af66fc99e Initial load
duke
parents:
diff changeset
1876 Interval* to_interval = interval_at_block_begin(to_block, reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1877
a61af66fc99e Initial load
duke
parents:
diff changeset
1878 if (phi != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1879 // phi function of the exception entry block
a61af66fc99e Initial load
duke
parents:
diff changeset
1880 // no moves are created for this phi function in the LIR_Generator, so the
a61af66fc99e Initial load
duke
parents:
diff changeset
1881 // interval at the throwing instruction must be searched using the operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1882 // of the phi function
a61af66fc99e Initial load
duke
parents:
diff changeset
1883 Value from_value = phi->operand_at(handler->phi_operand());
a61af66fc99e Initial load
duke
parents:
diff changeset
1884
a61af66fc99e Initial load
duke
parents:
diff changeset
1885 // with phi functions it can happen that the same from_value is used in
a61af66fc99e Initial load
duke
parents:
diff changeset
1886 // multiple mappings, so notify move-resolver that this is allowed
a61af66fc99e Initial load
duke
parents:
diff changeset
1887 move_resolver.set_multiple_reads_allowed();
a61af66fc99e Initial load
duke
parents:
diff changeset
1888
a61af66fc99e Initial load
duke
parents:
diff changeset
1889 Constant* con = from_value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
1890 if (con != NULL && !con->is_pinned()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1891 // unpinned constants may have no register, so add mapping from constant to interval
a61af66fc99e Initial load
duke
parents:
diff changeset
1892 move_resolver.add_mapping(LIR_OprFact::value_type(con->type()), to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1893 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1894 // search split child at the throwing op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
1895 Interval* from_interval = interval_at_op_id(from_value->operand()->vreg_number(), throwing_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1896 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1897 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1898
a61af66fc99e Initial load
duke
parents:
diff changeset
1899 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1900 // no phi function, so use reg_num also for from_interval
a61af66fc99e Initial load
duke
parents:
diff changeset
1901 // search split child at the throwing op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
1902 Interval* from_interval = interval_at_op_id(reg_num, throwing_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1903 if (from_interval != to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1904 // optimization to reduce number of moves: when to_interval is on stack and
a61af66fc99e Initial load
duke
parents:
diff changeset
1905 // the stack slot is known to be always correct, then no move is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
1906 if (!from_interval->always_in_memory() || from_interval->canonical_spill_slot() != to_interval->assigned_reg()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1907 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1908 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1909 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1910 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1911 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1912
a61af66fc99e Initial load
duke
parents:
diff changeset
1913 void LinearScan::resolve_exception_edge(XHandler* handler, int throwing_op_id, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1914 TRACE_LINEAR_SCAN(4, tty->print_cr("resolving exception handler B%d: throwing_op_id=%d", handler->entry_block()->block_id(), throwing_op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
1915
a61af66fc99e Initial load
duke
parents:
diff changeset
1916 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1917 assert(handler->lir_op_id() == -1, "already processed this xhandler");
a61af66fc99e Initial load
duke
parents:
diff changeset
1918 DEBUG_ONLY(handler->set_lir_op_id(throwing_op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
1919 assert(handler->entry_code() == NULL, "code already present");
a61af66fc99e Initial load
duke
parents:
diff changeset
1920
a61af66fc99e Initial load
duke
parents:
diff changeset
1921 // visit all registers where the live_in bit is set
a61af66fc99e Initial load
duke
parents:
diff changeset
1922 BlockBegin* block = handler->entry_block();
a61af66fc99e Initial load
duke
parents:
diff changeset
1923 int size = live_set_size();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1924 for (int r = (int)block->live_in().get_next_one_offset(0, size); r < size; r = (int)block->live_in().get_next_one_offset(r + 1, size)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1925 resolve_exception_edge(handler, throwing_op_id, r, NULL, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1926 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1927
a61af66fc99e Initial load
duke
parents:
diff changeset
1928 // the live_in bits are not set for phi functions of the xhandler entry, so iterate them separately
a61af66fc99e Initial load
duke
parents:
diff changeset
1929 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
1930 resolve_exception_edge(handler, throwing_op_id, phi->operand()->vreg_number(), phi, move_resolver)
a61af66fc99e Initial load
duke
parents:
diff changeset
1931 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1932
a61af66fc99e Initial load
duke
parents:
diff changeset
1933 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1934 LIR_List* entry_code = new LIR_List(compilation());
a61af66fc99e Initial load
duke
parents:
diff changeset
1935 move_resolver.set_insert_position(entry_code, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1936 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1937
a61af66fc99e Initial load
duke
parents:
diff changeset
1938 entry_code->jump(handler->entry_block());
a61af66fc99e Initial load
duke
parents:
diff changeset
1939 handler->set_entry_code(entry_code);
a61af66fc99e Initial load
duke
parents:
diff changeset
1940 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1941 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1942
a61af66fc99e Initial load
duke
parents:
diff changeset
1943
a61af66fc99e Initial load
duke
parents:
diff changeset
1944 void LinearScan::resolve_exception_handlers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1945 MoveResolver move_resolver(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
1946 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
1947 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1948
a61af66fc99e Initial load
duke
parents:
diff changeset
1949 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1950 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1951 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1952 if (block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1953 resolve_exception_entry(block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1954 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1955 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1956
a61af66fc99e Initial load
duke
parents:
diff changeset
1957 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1958 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1959 LIR_List* ops = block->lir();
a61af66fc99e Initial load
duke
parents:
diff changeset
1960 int num_ops = ops->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1961
a61af66fc99e Initial load
duke
parents:
diff changeset
1962 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
1963 assert(visitor.no_operands(ops->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1964 for (int j = 1; j < num_ops; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1965 LIR_Op* op = ops->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
1966 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1967
a61af66fc99e Initial load
duke
parents:
diff changeset
1968 if (op_id != -1 && has_info(op_id)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1969 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1970 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1971 assert(visitor.info_count() > 0, "should not visit otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1972
a61af66fc99e Initial load
duke
parents:
diff changeset
1973 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
1974 int n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1975 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1976 resolve_exception_edge(xhandlers->handler_at(k), op_id, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1977 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1978
a61af66fc99e Initial load
duke
parents:
diff changeset
1979 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1980 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1981 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1982 assert(visitor.all_xhandler()->length() == 0, "missed exception handler");
a61af66fc99e Initial load
duke
parents:
diff changeset
1983 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1984 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1985 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1986 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1987 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1988
a61af66fc99e Initial load
duke
parents:
diff changeset
1989
a61af66fc99e Initial load
duke
parents:
diff changeset
1990 // ********** Phase 7: assign register numbers back to LIR
a61af66fc99e Initial load
duke
parents:
diff changeset
1991 // (includes computation of debug information and oop maps)
a61af66fc99e Initial load
duke
parents:
diff changeset
1992
a61af66fc99e Initial load
duke
parents:
diff changeset
1993 VMReg LinearScan::vm_reg_for_interval(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1994 VMReg reg = interval->cached_vm_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
1995 if (!reg->is_valid() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1996 reg = vm_reg_for_operand(operand_for_interval(interval));
a61af66fc99e Initial load
duke
parents:
diff changeset
1997 interval->set_cached_vm_reg(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
1998 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1999 assert(reg == vm_reg_for_operand(operand_for_interval(interval)), "wrong cached value");
a61af66fc99e Initial load
duke
parents:
diff changeset
2000 return reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
2001 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2002
a61af66fc99e Initial load
duke
parents:
diff changeset
2003 VMReg LinearScan::vm_reg_for_operand(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2004 assert(opr->is_oop(), "currently only implemented for oop operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2005 return frame_map()->regname(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2006 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2007
a61af66fc99e Initial load
duke
parents:
diff changeset
2008
a61af66fc99e Initial load
duke
parents:
diff changeset
2009 LIR_Opr LinearScan::operand_for_interval(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2010 LIR_Opr opr = interval->cached_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2011 if (opr->is_illegal()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2012 opr = calc_operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
2013 interval->set_cached_opr(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2014 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2015
a61af66fc99e Initial load
duke
parents:
diff changeset
2016 assert(opr == calc_operand_for_interval(interval), "wrong cached value");
a61af66fc99e Initial load
duke
parents:
diff changeset
2017 return opr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2018 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2019
a61af66fc99e Initial load
duke
parents:
diff changeset
2020 LIR_Opr LinearScan::calc_operand_for_interval(const Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2021 int assigned_reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2022 BasicType type = interval->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
2023
a61af66fc99e Initial load
duke
parents:
diff changeset
2024 if (assigned_reg >= nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2025 // stack slot
a61af66fc99e Initial load
duke
parents:
diff changeset
2026 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2027 return LIR_OprFact::stack(assigned_reg - nof_regs, type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2028
a61af66fc99e Initial load
duke
parents:
diff changeset
2029 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2030 // register
a61af66fc99e Initial load
duke
parents:
diff changeset
2031 switch (type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2032 case T_OBJECT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2033 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2034 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2035 return LIR_OprFact::single_cpu_oop(assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2036 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2037
1816
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2038 case T_ADDRESS: {
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2039 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
2040 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
2041 return LIR_OprFact::single_cpu_address(assigned_reg);
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2042 }
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2043
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2044 #ifdef __SOFTFP__
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2045 case T_FLOAT: // fall through
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2046 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2047 case T_INT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2048 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2049 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2050 return LIR_OprFact::single_cpu(assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2051 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2052
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2053 #ifdef __SOFTFP__
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2054 case T_DOUBLE: // fall through
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2055 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2056 case T_LONG: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2057 int assigned_regHi = interval->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
2058 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2059 assert(num_physical_regs(T_LONG) == 1 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2060 (assigned_regHi >= pd_first_cpu_reg && assigned_regHi <= pd_last_cpu_reg), "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2061
a61af66fc99e Initial load
duke
parents:
diff changeset
2062 assert(assigned_reg != assigned_regHi, "invalid allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
2063 assert(num_physical_regs(T_LONG) == 1 || assigned_reg < assigned_regHi,
a61af66fc99e Initial load
duke
parents:
diff changeset
2064 "register numbers must be sorted (ensure that e.g. a move from eax,ebx to ebx,eax can not occur)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2065 assert((assigned_regHi != any_reg) ^ (num_physical_regs(T_LONG) == 1), "must be match");
a61af66fc99e Initial load
duke
parents:
diff changeset
2066 if (requires_adjacent_regs(T_LONG)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2067 assert(assigned_reg % 2 == 0 && assigned_reg + 1 == assigned_regHi, "must be sequential and even");
a61af66fc99e Initial load
duke
parents:
diff changeset
2068 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2069
a61af66fc99e Initial load
duke
parents:
diff changeset
2070 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
2071 return LIR_OprFact::double_cpu(assigned_reg, assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2072 #else
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2073 #if defined(SPARC) || defined(PPC)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2074 return LIR_OprFact::double_cpu(assigned_regHi, assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2075 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2076 return LIR_OprFact::double_cpu(assigned_reg, assigned_regHi);
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2077 #endif // SPARC
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2078 #endif // LP64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2079 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2080
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2081 #ifndef __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2082 case T_FLOAT: {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2083 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2084 if (UseSSE >= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2085 assert(assigned_reg >= pd_first_xmm_reg && assigned_reg <= pd_last_xmm_reg, "no xmm register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2086 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2087 return LIR_OprFact::single_xmm(assigned_reg - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2088 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2089 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2090
a61af66fc99e Initial load
duke
parents:
diff changeset
2091 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2092 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2093 return LIR_OprFact::single_fpu(assigned_reg - pd_first_fpu_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2094 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2095
a61af66fc99e Initial load
duke
parents:
diff changeset
2096 case T_DOUBLE: {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2097 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2098 if (UseSSE >= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2099 assert(assigned_reg >= pd_first_xmm_reg && assigned_reg <= pd_last_xmm_reg, "no xmm register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2100 assert(interval->assigned_regHi() == any_reg, "must not have hi register (double xmm values are stored in one register)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2101 return LIR_OprFact::double_xmm(assigned_reg - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2103 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2104
a61af66fc99e Initial load
duke
parents:
diff changeset
2105 #ifdef SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
2106 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2107 assert(interval->assigned_regHi() >= pd_first_fpu_reg && interval->assigned_regHi() <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2108 assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even");
a61af66fc99e Initial load
duke
parents:
diff changeset
2109 LIR_Opr result = LIR_OprFact::double_fpu(interval->assigned_regHi() - pd_first_fpu_reg, assigned_reg - pd_first_fpu_reg);
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2110 #elif defined(ARM)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2111 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
2112 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
2113 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
2114 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
2115 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2116 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2117 assert(interval->assigned_regHi() == any_reg, "must not have hi register (double fpu values are stored in one register on Intel)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2118 LIR_Opr result = LIR_OprFact::double_fpu(assigned_reg - pd_first_fpu_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2119 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2120 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
2121 }
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2122 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2123
a61af66fc99e Initial load
duke
parents:
diff changeset
2124 default: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2125 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2126 return LIR_OprFact::illegalOpr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2127 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2128 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2129 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2130 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2131
a61af66fc99e Initial load
duke
parents:
diff changeset
2132 LIR_Opr LinearScan::canonical_spill_opr(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2133 assert(interval->canonical_spill_slot() >= nof_regs, "canonical spill slot not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
2134 return LIR_OprFact::stack(interval->canonical_spill_slot() - nof_regs, interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
2135 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2136
a61af66fc99e Initial load
duke
parents:
diff changeset
2137 LIR_Opr LinearScan::color_lir_opr(LIR_Opr opr, int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2138 assert(opr->is_virtual(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2139
a61af66fc99e Initial load
duke
parents:
diff changeset
2140 Interval* interval = interval_at(opr->vreg_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
2141 assert(interval != NULL, "interval must exist");
a61af66fc99e Initial load
duke
parents:
diff changeset
2142
a61af66fc99e Initial load
duke
parents:
diff changeset
2143 if (op_id != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2144 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2145 BlockBegin* block = block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2146 if (block->number_of_sux() <= 1 && op_id == block->last_lir_instruction_id()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2147 // check if spill moves could have been appended at the end of this block, but
a61af66fc99e Initial load
duke
parents:
diff changeset
2148 // before the branch instruction. So the split child information for this branch would
a61af66fc99e Initial load
duke
parents:
diff changeset
2149 // be incorrect.
a61af66fc99e Initial load
duke
parents:
diff changeset
2150 LIR_OpBranch* branch = block->lir()->instructions_list()->last()->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
2151 if (branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2152 if (block->live_out().at(opr->vreg_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2153 assert(branch->cond() == lir_cond_always, "block does not end with an unconditional jump");
a61af66fc99e Initial load
duke
parents:
diff changeset
2154 assert(false, "can't get split child for the last branch of a block because the information would be incorrect (moves are inserted before the branch in resolve_data_flow)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2155 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2157 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2158 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2159
a61af66fc99e Initial load
duke
parents:
diff changeset
2160 // operands are not changed when an interval is split during allocation,
a61af66fc99e Initial load
duke
parents:
diff changeset
2161 // so search the right interval here
a61af66fc99e Initial load
duke
parents:
diff changeset
2162 interval = split_child_at_op_id(interval, op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2163 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2164
a61af66fc99e Initial load
duke
parents:
diff changeset
2165 LIR_Opr res = operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
2166
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2167 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2168 // new semantic for is_last_use: not only set on definite end of interval,
a61af66fc99e Initial load
duke
parents:
diff changeset
2169 // but also before hole
a61af66fc99e Initial load
duke
parents:
diff changeset
2170 // This may still miss some cases (e.g. for dead values), but it is not necessary that the
a61af66fc99e Initial load
duke
parents:
diff changeset
2171 // last use information is completely correct
a61af66fc99e Initial load
duke
parents:
diff changeset
2172 // information is only needed for fpu stack allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
2173 if (res->is_fpu_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2174 if (opr->is_last_use() || op_id == interval->to() || (op_id != -1 && interval->has_hole_between(op_id, op_id + 1))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2175 assert(op_id == -1 || !is_block_begin(op_id), "holes at begin of block may also result from control flow");
a61af66fc99e Initial load
duke
parents:
diff changeset
2176 res = res->make_last_use();
a61af66fc99e Initial load
duke
parents:
diff changeset
2177 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2179 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2180
a61af66fc99e Initial load
duke
parents:
diff changeset
2181 assert(!gen()->is_vreg_flag_set(opr->vreg_number(), LIRGenerator::callee_saved) || !FrameMap::is_caller_save_register(res), "bad allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
2182
a61af66fc99e Initial load
duke
parents:
diff changeset
2183 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
2184 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2185
a61af66fc99e Initial load
duke
parents:
diff changeset
2186
a61af66fc99e Initial load
duke
parents:
diff changeset
2187 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2188 // some methods used to check correctness of debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
2189
a61af66fc99e Initial load
duke
parents:
diff changeset
2190 void assert_no_register_values(GrowableArray<ScopeValue*>* values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2191 if (values == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2192 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
2193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2194
a61af66fc99e Initial load
duke
parents:
diff changeset
2195 for (int i = 0; i < values->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2196 ScopeValue* value = values->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2197
a61af66fc99e Initial load
duke
parents:
diff changeset
2198 if (value->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2199 Location location = ((LocationValue*)value)->location();
a61af66fc99e Initial load
duke
parents:
diff changeset
2200 assert(location.where() == Location::on_stack, "value is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2201 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2204
a61af66fc99e Initial load
duke
parents:
diff changeset
2205 void assert_no_register_values(GrowableArray<MonitorValue*>* values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2206 if (values == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2207 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
2208 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2209
a61af66fc99e Initial load
duke
parents:
diff changeset
2210 for (int i = 0; i < values->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2211 MonitorValue* value = values->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2212
a61af66fc99e Initial load
duke
parents:
diff changeset
2213 if (value->owner()->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2214 Location location = ((LocationValue*)value->owner())->location();
a61af66fc99e Initial load
duke
parents:
diff changeset
2215 assert(location.where() == Location::on_stack, "owner is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2217 assert(value->basic_lock().where() == Location::on_stack, "basic_lock is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2218 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2219 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2220
a61af66fc99e Initial load
duke
parents:
diff changeset
2221 void assert_equal(Location l1, Location l2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2222 assert(l1.where() == l2.where() && l1.type() == l2.type() && l1.offset() == l2.offset(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2223 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2224
a61af66fc99e Initial load
duke
parents:
diff changeset
2225 void assert_equal(ScopeValue* v1, ScopeValue* v2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2226 if (v1->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2227 assert(v2->is_location(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2228 assert_equal(((LocationValue*)v1)->location(), ((LocationValue*)v2)->location());
a61af66fc99e Initial load
duke
parents:
diff changeset
2229 } else if (v1->is_constant_int()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2230 assert(v2->is_constant_int(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2231 assert(((ConstantIntValue*)v1)->value() == ((ConstantIntValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2232 } else if (v1->is_constant_double()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2233 assert(v2->is_constant_double(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2234 assert(((ConstantDoubleValue*)v1)->value() == ((ConstantDoubleValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2235 } else if (v1->is_constant_long()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2236 assert(v2->is_constant_long(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2237 assert(((ConstantLongValue*)v1)->value() == ((ConstantLongValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2238 } else if (v1->is_constant_oop()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2239 assert(v2->is_constant_oop(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2240 assert(((ConstantOopWriteValue*)v1)->value() == ((ConstantOopWriteValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2241 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2242 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2243 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2244 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2245
a61af66fc99e Initial load
duke
parents:
diff changeset
2246 void assert_equal(MonitorValue* m1, MonitorValue* m2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2247 assert_equal(m1->owner(), m2->owner());
a61af66fc99e Initial load
duke
parents:
diff changeset
2248 assert_equal(m1->basic_lock(), m2->basic_lock());
a61af66fc99e Initial load
duke
parents:
diff changeset
2249 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2250
a61af66fc99e Initial load
duke
parents:
diff changeset
2251 void assert_equal(IRScopeDebugInfo* d1, IRScopeDebugInfo* d2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2252 assert(d1->scope() == d2->scope(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2253 assert(d1->bci() == d2->bci(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2254
a61af66fc99e Initial load
duke
parents:
diff changeset
2255 if (d1->locals() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2256 assert(d1->locals() != NULL && d2->locals() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2257 assert(d1->locals()->length() == d2->locals()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2258 for (int i = 0; i < d1->locals()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2259 assert_equal(d1->locals()->at(i), d2->locals()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2260 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2261 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2262 assert(d1->locals() == NULL && d2->locals() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2263 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2264
a61af66fc99e Initial load
duke
parents:
diff changeset
2265 if (d1->expressions() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2266 assert(d1->expressions() != NULL && d2->expressions() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2267 assert(d1->expressions()->length() == d2->expressions()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2268 for (int i = 0; i < d1->expressions()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2269 assert_equal(d1->expressions()->at(i), d2->expressions()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2270 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2271 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2272 assert(d1->expressions() == NULL && d2->expressions() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2273 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2274
a61af66fc99e Initial load
duke
parents:
diff changeset
2275 if (d1->monitors() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2276 assert(d1->monitors() != NULL && d2->monitors() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2277 assert(d1->monitors()->length() == d2->monitors()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2278 for (int i = 0; i < d1->monitors()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2279 assert_equal(d1->monitors()->at(i), d2->monitors()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2280 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2281 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2282 assert(d1->monitors() == NULL && d2->monitors() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2283 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2284
a61af66fc99e Initial load
duke
parents:
diff changeset
2285 if (d1->caller() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2286 assert(d1->caller() != NULL && d2->caller() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2287 assert_equal(d1->caller(), d2->caller());
a61af66fc99e Initial load
duke
parents:
diff changeset
2288 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2289 assert(d1->caller() == NULL && d2->caller() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2290 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2291 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2292
a61af66fc99e Initial load
duke
parents:
diff changeset
2293 void check_stack_depth(CodeEmitInfo* info, int stack_end) {
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2294 if (info->stack()->bci() != SynchronizationEntryBCI && !info->scope()->method()->is_native()) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2295 Bytecodes::Code code = info->scope()->method()->java_code_at_bci(info->stack()->bci());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2296 switch (code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2297 case Bytecodes::_ifnull : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2298 case Bytecodes::_ifnonnull : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2299 case Bytecodes::_ifeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2300 case Bytecodes::_ifne : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2301 case Bytecodes::_iflt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2302 case Bytecodes::_ifge : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2303 case Bytecodes::_ifgt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2304 case Bytecodes::_ifle : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2305 case Bytecodes::_if_icmpeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2306 case Bytecodes::_if_icmpne : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2307 case Bytecodes::_if_icmplt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2308 case Bytecodes::_if_icmpge : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2309 case Bytecodes::_if_icmpgt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2310 case Bytecodes::_if_icmple : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2311 case Bytecodes::_if_acmpeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2312 case Bytecodes::_if_acmpne :
a61af66fc99e Initial load
duke
parents:
diff changeset
2313 assert(stack_end >= -Bytecodes::depth(code), "must have non-empty expression stack at if bytecode");
a61af66fc99e Initial load
duke
parents:
diff changeset
2314 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2315 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2316 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2317 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2318
a61af66fc99e Initial load
duke
parents:
diff changeset
2319 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2320
a61af66fc99e Initial load
duke
parents:
diff changeset
2321
a61af66fc99e Initial load
duke
parents:
diff changeset
2322 IntervalWalker* LinearScan::init_compute_oop_maps() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2323 // setup lists of potential oops for walking
a61af66fc99e Initial load
duke
parents:
diff changeset
2324 Interval* oop_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
2325 Interval* non_oop_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
2326
a61af66fc99e Initial load
duke
parents:
diff changeset
2327 create_unhandled_lists(&oop_intervals, &non_oop_intervals, is_oop_interval, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2328
a61af66fc99e Initial load
duke
parents:
diff changeset
2329 // intervals that have no oops inside need not to be processed
a61af66fc99e Initial load
duke
parents:
diff changeset
2330 // to ensure a walking until the last instruction id, add a dummy interval
a61af66fc99e Initial load
duke
parents:
diff changeset
2331 // with a high operation id
a61af66fc99e Initial load
duke
parents:
diff changeset
2332 non_oop_intervals = new Interval(any_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2333 non_oop_intervals->add_range(max_jint - 2, max_jint - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2334
a61af66fc99e Initial load
duke
parents:
diff changeset
2335 return new IntervalWalker(this, oop_intervals, non_oop_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2336 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2337
a61af66fc99e Initial load
duke
parents:
diff changeset
2338
a61af66fc99e Initial load
duke
parents:
diff changeset
2339 OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo* info, bool is_call_site) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2340 TRACE_LINEAR_SCAN(3, tty->print_cr("creating oop map at op_id %d", op->id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2341
a61af66fc99e Initial load
duke
parents:
diff changeset
2342 // walk before the current operation -> intervals that start at
a61af66fc99e Initial load
duke
parents:
diff changeset
2343 // the operation (= output operands of the operation) are not
a61af66fc99e Initial load
duke
parents:
diff changeset
2344 // included in the oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2345 iw->walk_before(op->id());
a61af66fc99e Initial load
duke
parents:
diff changeset
2346
a61af66fc99e Initial load
duke
parents:
diff changeset
2347 int frame_size = frame_map()->framesize();
a61af66fc99e Initial load
duke
parents:
diff changeset
2348 int arg_count = frame_map()->oop_map_arg_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
2349 OopMap* map = new OopMap(frame_size, arg_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2350
a61af66fc99e Initial load
duke
parents:
diff changeset
2351 // Check if this is a patch site.
a61af66fc99e Initial load
duke
parents:
diff changeset
2352 bool is_patch_info = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
2353 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2354 assert(!is_call_site, "move must not be a call site");
a61af66fc99e Initial load
duke
parents:
diff changeset
2355 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
2356 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
2357
a61af66fc99e Initial load
duke
parents:
diff changeset
2358 is_patch_info = move->patch_code() != lir_patch_none;
a61af66fc99e Initial load
duke
parents:
diff changeset
2359 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2360
a61af66fc99e Initial load
duke
parents:
diff changeset
2361 // Iterate through active intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
2362 for (Interval* interval = iw->active_first(fixedKind); interval != Interval::end(); interval = interval->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2363 int assigned_reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2364
a61af66fc99e Initial load
duke
parents:
diff changeset
2365 assert(interval->current_from() <= op->id() && op->id() <= interval->current_to(), "interval should not be active otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2366 assert(interval->assigned_regHi() == any_reg, "oop must be single word");
a61af66fc99e Initial load
duke
parents:
diff changeset
2367 assert(interval->reg_num() >= LIR_OprDesc::vreg_base, "fixed interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
2368
a61af66fc99e Initial load
duke
parents:
diff changeset
2369 // Check if this range covers the instruction. Intervals that
a61af66fc99e Initial load
duke
parents:
diff changeset
2370 // start or end at the current operation are not included in the
a61af66fc99e Initial load
duke
parents:
diff changeset
2371 // oop map, except in the case of patching moves. For patching
a61af66fc99e Initial load
duke
parents:
diff changeset
2372 // moves, any intervals which end at this instruction are included
a61af66fc99e Initial load
duke
parents:
diff changeset
2373 // in the oop map since we may safepoint while doing the patch
a61af66fc99e Initial load
duke
parents:
diff changeset
2374 // before we've consumed the inputs.
a61af66fc99e Initial load
duke
parents:
diff changeset
2375 if (is_patch_info || op->id() < interval->current_to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2376
a61af66fc99e Initial load
duke
parents:
diff changeset
2377 // caller-save registers must not be included into oop-maps at calls
a61af66fc99e Initial load
duke
parents:
diff changeset
2378 assert(!is_call_site || assigned_reg >= nof_regs || !is_caller_save(assigned_reg), "interval is in a caller-save register at a call -> register will be overwritten");
a61af66fc99e Initial load
duke
parents:
diff changeset
2379
a61af66fc99e Initial load
duke
parents:
diff changeset
2380 VMReg name = vm_reg_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
2381 map->set_oop(name);
a61af66fc99e Initial load
duke
parents:
diff changeset
2382
a61af66fc99e Initial load
duke
parents:
diff changeset
2383 // Spill optimization: when the stack value is guaranteed to be always correct,
a61af66fc99e Initial load
duke
parents:
diff changeset
2384 // then it must be added to the oop map even if the interval is currently in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
2385 if (interval->always_in_memory() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2386 op->id() > interval->spill_definition_pos() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2387 interval->assigned_reg() != interval->canonical_spill_slot()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2388 assert(interval->spill_definition_pos() > 0, "position not set correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
2389 assert(interval->canonical_spill_slot() >= LinearScan::nof_regs, "no spill slot assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
2390 assert(interval->assigned_reg() < LinearScan::nof_regs, "interval is on stack, so stack slot is registered twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
2391
a61af66fc99e Initial load
duke
parents:
diff changeset
2392 map->set_oop(frame_map()->slot_regname(interval->canonical_spill_slot() - LinearScan::nof_regs));
a61af66fc99e Initial load
duke
parents:
diff changeset
2393 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2394 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2395 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2396
a61af66fc99e Initial load
duke
parents:
diff changeset
2397 // add oops from lock stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2398 assert(info->stack() != NULL, "CodeEmitInfo must always have a stack");
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2399 int locks_count = info->stack()->total_locks_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2400 for (int i = 0; i < locks_count; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2401 map->set_oop(frame_map()->monitor_object_regname(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2402 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2403
a61af66fc99e Initial load
duke
parents:
diff changeset
2404 return map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2405 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2406
a61af66fc99e Initial load
duke
parents:
diff changeset
2407
a61af66fc99e Initial load
duke
parents:
diff changeset
2408 void LinearScan::compute_oop_map(IntervalWalker* iw, const LIR_OpVisitState &visitor, LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2409 assert(visitor.info_count() > 0, "no oop map needed");
a61af66fc99e Initial load
duke
parents:
diff changeset
2410
a61af66fc99e Initial load
duke
parents:
diff changeset
2411 // compute oop_map only for first CodeEmitInfo
a61af66fc99e Initial load
duke
parents:
diff changeset
2412 // because it is (in most cases) equal for all other infos of the same operation
a61af66fc99e Initial load
duke
parents:
diff changeset
2413 CodeEmitInfo* first_info = visitor.info_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2414 OopMap* first_oop_map = compute_oop_map(iw, op, first_info, visitor.has_call());
a61af66fc99e Initial load
duke
parents:
diff changeset
2415
a61af66fc99e Initial load
duke
parents:
diff changeset
2416 for (int i = 0; i < visitor.info_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2417 CodeEmitInfo* info = visitor.info_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2418 OopMap* oop_map = first_oop_map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2419
a61af66fc99e Initial load
duke
parents:
diff changeset
2420 if (info->stack()->locks_size() != first_info->stack()->locks_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2421 // this info has a different number of locks then the precomputed oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2422 // (possible for lock and unlock instructions) -> compute oop map with
a61af66fc99e Initial load
duke
parents:
diff changeset
2423 // correct lock information
a61af66fc99e Initial load
duke
parents:
diff changeset
2424 oop_map = compute_oop_map(iw, op, info, visitor.has_call());
a61af66fc99e Initial load
duke
parents:
diff changeset
2425 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2426
a61af66fc99e Initial load
duke
parents:
diff changeset
2427 if (info->_oop_map == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2428 info->_oop_map = oop_map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2429 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2430 // a CodeEmitInfo can not be shared between different LIR-instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
2431 // because interval splitting can occur anywhere between two instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
2432 // and so the oop maps must be different
a61af66fc99e Initial load
duke
parents:
diff changeset
2433 // -> check if the already set oop_map is exactly the one calculated for this operation
a61af66fc99e Initial load
duke
parents:
diff changeset
2434 assert(info->_oop_map == oop_map, "same CodeEmitInfo used for multiple LIR instructions");
a61af66fc99e Initial load
duke
parents:
diff changeset
2435 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2436 }
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 // frequently used constants
a61af66fc99e Initial load
duke
parents:
diff changeset
2441 ConstantOopWriteValue LinearScan::_oop_null_scope_value = ConstantOopWriteValue(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2442 ConstantIntValue LinearScan::_int_m1_scope_value = ConstantIntValue(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2443 ConstantIntValue LinearScan::_int_0_scope_value = ConstantIntValue(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2444 ConstantIntValue LinearScan::_int_1_scope_value = ConstantIntValue(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2445 ConstantIntValue LinearScan::_int_2_scope_value = ConstantIntValue(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
2446 LocationValue _illegal_value = LocationValue(Location());
a61af66fc99e Initial load
duke
parents:
diff changeset
2447
a61af66fc99e Initial load
duke
parents:
diff changeset
2448 void LinearScan::init_compute_debug_info() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2449 // cache for frequently used scope values
a61af66fc99e Initial load
duke
parents:
diff changeset
2450 // (cpu registers and stack slots)
a61af66fc99e Initial load
duke
parents:
diff changeset
2451 _scope_value_cache = ScopeValueArray((LinearScan::nof_cpu_regs + frame_map()->argcount() + max_spills()) * 2, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2452 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2453
a61af66fc99e Initial load
duke
parents:
diff changeset
2454 MonitorValue* LinearScan::location_for_monitor_index(int monitor_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2455 Location loc;
a61af66fc99e Initial load
duke
parents:
diff changeset
2456 if (!frame_map()->location_for_monitor_object(monitor_index, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2457 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2458 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2459 ScopeValue* object_scope_value = new LocationValue(loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2460
a61af66fc99e Initial load
duke
parents:
diff changeset
2461 if (!frame_map()->location_for_monitor_lock(monitor_index, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2462 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2463 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2464 return new MonitorValue(object_scope_value, loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2465 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2466
a61af66fc99e Initial load
duke
parents:
diff changeset
2467 LocationValue* LinearScan::location_for_name(int name, Location::Type loc_type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2468 Location loc;
a61af66fc99e Initial load
duke
parents:
diff changeset
2469 if (!frame_map()->locations_for_slot(name, loc_type, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2470 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2471 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2472 return new LocationValue(loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2474
a61af66fc99e Initial load
duke
parents:
diff changeset
2475
a61af66fc99e Initial load
duke
parents:
diff changeset
2476 int LinearScan::append_scope_value_for_constant(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2477 assert(opr->is_constant(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2478
a61af66fc99e Initial load
duke
parents:
diff changeset
2479 LIR_Const* c = opr->as_constant_ptr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2480 BasicType t = c->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
2481 switch (t) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2482 case T_OBJECT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2483 jobject value = c->as_jobject();
a61af66fc99e Initial load
duke
parents:
diff changeset
2484 if (value == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2485 scope_values->append(&_oop_null_scope_value);
a61af66fc99e Initial load
duke
parents:
diff changeset
2486 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2487 scope_values->append(new ConstantOopWriteValue(c->as_jobject()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2489 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2490 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2491
a61af66fc99e Initial load
duke
parents:
diff changeset
2492 case T_INT: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2493 case T_FLOAT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2494 int value = c->as_jint_bits();
a61af66fc99e Initial load
duke
parents:
diff changeset
2495 switch (value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2496 case -1: scope_values->append(&_int_m1_scope_value); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2497 case 0: scope_values->append(&_int_0_scope_value); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2498 case 1: scope_values->append(&_int_1_scope_value); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2499 case 2: scope_values->append(&_int_2_scope_value); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2500 default: scope_values->append(new ConstantIntValue(c->as_jint_bits())); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2501 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2502 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2503 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2504
a61af66fc99e Initial load
duke
parents:
diff changeset
2505 case T_LONG: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2506 case T_DOUBLE: {
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2507 #ifdef _LP64
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2508 scope_values->append(&_int_0_scope_value);
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2509 scope_values->append(new ConstantLongValue(c->as_jlong_bits()));
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2510 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2511 if (hi_word_offset_in_bytes > lo_word_offset_in_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2512 scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2513 scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2514 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2515 scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2516 scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2517 }
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2518 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2519 return 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2520 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2521
1297
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2522 case T_ADDRESS: {
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2523 #ifdef _LP64
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2524 scope_values->append(new ConstantLongValue(c->as_jint()));
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2525 #else
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2526 scope_values->append(new ConstantIntValue(c->as_jint()));
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2527 #endif
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2528 return 1;
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2529 }
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2530
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2531 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
2532 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2533 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2534 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2535 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2536
a61af66fc99e Initial load
duke
parents:
diff changeset
2537 int LinearScan::append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2538 if (opr->is_single_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2539 int stack_idx = opr->single_stack_ix();
a61af66fc99e Initial load
duke
parents:
diff changeset
2540 bool is_oop = opr->is_oop_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
2541 int cache_idx = (stack_idx + LinearScan::nof_cpu_regs) * 2 + (is_oop ? 1 : 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2542
a61af66fc99e Initial load
duke
parents:
diff changeset
2543 ScopeValue* sv = _scope_value_cache.at(cache_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
2544 if (sv == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2545 Location::Type loc_type = is_oop ? Location::oop : Location::normal;
a61af66fc99e Initial load
duke
parents:
diff changeset
2546 sv = location_for_name(stack_idx, loc_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2547 _scope_value_cache.at_put(cache_idx, sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2548 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2549
a61af66fc99e Initial load
duke
parents:
diff changeset
2550 // check if cached value is correct
a61af66fc99e Initial load
duke
parents:
diff changeset
2551 DEBUG_ONLY(assert_equal(sv, location_for_name(stack_idx, is_oop ? Location::oop : Location::normal)));
a61af66fc99e Initial load
duke
parents:
diff changeset
2552
a61af66fc99e Initial load
duke
parents:
diff changeset
2553 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2554 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2555
a61af66fc99e Initial load
duke
parents:
diff changeset
2556 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2557 bool is_oop = opr->is_oop_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
2558 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
2559 Location::Type int_loc_type = NOT_LP64(Location::normal) LP64_ONLY(Location::int_in_long);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2560
a61af66fc99e Initial load
duke
parents:
diff changeset
2561 ScopeValue* sv = _scope_value_cache.at(cache_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
2562 if (sv == NULL) {
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2563 Location::Type loc_type = is_oop ? Location::oop : int_loc_type;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2564 VMReg rname = frame_map()->regname(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2565 sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2566 _scope_value_cache.at_put(cache_idx, sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2567 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2568
a61af66fc99e Initial load
duke
parents:
diff changeset
2569 // check if cached value is correct
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2570 DEBUG_ONLY(assert_equal(sv, new LocationValue(Location::new_reg_loc(is_oop ? Location::oop : int_loc_type, frame_map()->regname(opr)))));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2571
a61af66fc99e Initial load
duke
parents:
diff changeset
2572 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2573 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2574
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2575 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2576 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2577 VMReg rname = opr->as_xmm_float_reg()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2578 LocationValue* sv = new LocationValue(Location::new_reg_loc(Location::normal, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2579
a61af66fc99e Initial load
duke
parents:
diff changeset
2580 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2581 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2582 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2583
a61af66fc99e Initial load
duke
parents:
diff changeset
2584 } else if (opr->is_single_fpu()) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2585 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2586 // the exact location of fpu stack values is only known
a61af66fc99e Initial load
duke
parents:
diff changeset
2587 // during fpu stack allocation, so the stack allocator object
a61af66fc99e Initial load
duke
parents:
diff changeset
2588 // must be present
a61af66fc99e Initial load
duke
parents:
diff changeset
2589 assert(use_fpu_stack_allocation(), "should not have float stack values without fpu stack allocation (all floats must be SSE2)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2590 assert(_fpu_stack_allocator != NULL, "must be present");
a61af66fc99e Initial load
duke
parents:
diff changeset
2591 opr = _fpu_stack_allocator->to_fpu_stack(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2592 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2593
a61af66fc99e Initial load
duke
parents:
diff changeset
2594 Location::Type loc_type = float_saved_as_double ? Location::float_in_dbl : Location::normal;
a61af66fc99e Initial load
duke
parents:
diff changeset
2595 VMReg rname = frame_map()->fpu_regname(opr->fpu_regnr());
a61af66fc99e Initial load
duke
parents:
diff changeset
2596 LocationValue* sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2597
a61af66fc99e Initial load
duke
parents:
diff changeset
2598 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2599 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2600
a61af66fc99e Initial load
duke
parents:
diff changeset
2601 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2602 // double-size operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2603
a61af66fc99e Initial load
duke
parents:
diff changeset
2604 ScopeValue* first;
a61af66fc99e Initial load
duke
parents:
diff changeset
2605 ScopeValue* second;
a61af66fc99e Initial load
duke
parents:
diff changeset
2606
a61af66fc99e Initial load
duke
parents:
diff changeset
2607 if (opr->is_double_stack()) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2608 #ifdef _LP64
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2609 Location loc1;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2610 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
2611 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
2612 bailout("too large frame");
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2613 }
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2614 // Does this reverse on x86 vs. sparc?
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2615 first = new LocationValue(loc1);
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2616 second = &_int_0_scope_value;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2617 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2618 Location loc1, loc2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2619 if (!frame_map()->locations_for_slot(opr->double_stack_ix(), Location::normal, &loc1, &loc2)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2620 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2621 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2622 first = new LocationValue(loc1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2623 second = new LocationValue(loc2);
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2624 #endif // _LP64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2625
a61af66fc99e Initial load
duke
parents:
diff changeset
2626 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2627 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
2628 VMReg rname_first = opr->as_register_lo()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2629 first = new LocationValue(Location::new_reg_loc(Location::lng, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2630 second = &_int_0_scope_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
2631 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2632 VMReg rname_first = opr->as_register_lo()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2633 VMReg rname_second = opr->as_register_hi()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2634
a61af66fc99e Initial load
duke
parents:
diff changeset
2635 if (hi_word_offset_in_bytes < lo_word_offset_in_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2636 // lo/hi and swapped relative to first and second, so swap them
a61af66fc99e Initial load
duke
parents:
diff changeset
2637 VMReg tmp = rname_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
2638 rname_first = rname_second;
a61af66fc99e Initial load
duke
parents:
diff changeset
2639 rname_second = tmp;
a61af66fc99e Initial load
duke
parents:
diff changeset
2640 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2641
a61af66fc99e Initial load
duke
parents:
diff changeset
2642 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2643 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
2644 #endif //_LP64
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2645
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2646
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2647 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2648 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2649 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
2650 VMReg rname_first = opr->as_xmm_double_reg()->as_VMReg();
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2651 # ifdef _LP64
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2652 first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first));
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2653 second = &_int_0_scope_value;
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2654 # else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2655 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2656 // %%% This is probably a waste but we'll keep things as they were for now
a61af66fc99e Initial load
duke
parents:
diff changeset
2657 if (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2658 VMReg rname_second = rname_first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
2659 second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
a61af66fc99e Initial load
duke
parents:
diff changeset
2660 }
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2661 # endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2662 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2663
a61af66fc99e Initial load
duke
parents:
diff changeset
2664 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2665 // 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
2666 // the double as float registers in the native ordering. On X86,
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2667 // fpu_regnrLo is a FPU stack slot whose VMReg represents
a61af66fc99e Initial load
duke
parents:
diff changeset
2668 // the low-order word of the double and fpu_regnrLo + 1 is the
a61af66fc99e Initial load
duke
parents:
diff changeset
2669 // name for the other half. *first and *second must represent the
a61af66fc99e Initial load
duke
parents:
diff changeset
2670 // least and most significant words, respectively.
a61af66fc99e Initial load
duke
parents:
diff changeset
2671
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2672 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2673 // the exact location of fpu stack values is only known
a61af66fc99e Initial load
duke
parents:
diff changeset
2674 // during fpu stack allocation, so the stack allocator object
a61af66fc99e Initial load
duke
parents:
diff changeset
2675 // must be present
a61af66fc99e Initial load
duke
parents:
diff changeset
2676 assert(use_fpu_stack_allocation(), "should not have float stack values without fpu stack allocation (all floats must be SSE2)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2677 assert(_fpu_stack_allocator != NULL, "must be present");
a61af66fc99e Initial load
duke
parents:
diff changeset
2678 opr = _fpu_stack_allocator->to_fpu_stack(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2679
a61af66fc99e Initial load
duke
parents:
diff changeset
2680 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrHi is used)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2681 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2682 #ifdef SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
2683 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi() + 1, "assumed in calculation (only fpu_regnrHi is used)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2684 #endif
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2685 #ifdef ARM
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2686 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
2687 #endif
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2688 #ifdef PPC
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2689 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
2690 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2691
a61af66fc99e Initial load
duke
parents:
diff changeset
2692 VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrHi());
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2693 #ifdef _LP64
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2694 first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first));
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2695 second = &_int_0_scope_value;
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2696 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2697 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2698 // %%% This is probably a waste but we'll keep things as they were for now
a61af66fc99e Initial load
duke
parents:
diff changeset
2699 if (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2700 VMReg rname_second = rname_first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
2701 second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
a61af66fc99e Initial load
duke
parents:
diff changeset
2702 }
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2703 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2704
a61af66fc99e Initial load
duke
parents:
diff changeset
2705 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2706 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2707 first = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2708 second = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2709 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2710
a61af66fc99e Initial load
duke
parents:
diff changeset
2711 assert(first != NULL && second != NULL, "must be set");
a61af66fc99e Initial load
duke
parents:
diff changeset
2712 // The convention the interpreter uses is that the second local
a61af66fc99e Initial load
duke
parents:
diff changeset
2713 // holds the first raw word of the native double representation.
a61af66fc99e Initial load
duke
parents:
diff changeset
2714 // This is actually reasonable, since locals and stack arrays
a61af66fc99e Initial load
duke
parents:
diff changeset
2715 // grow downwards in all implementations.
a61af66fc99e Initial load
duke
parents:
diff changeset
2716 // (If, on some machine, the interpreter's Java locals or stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2717 // were to grow upwards, the embedded doubles would be word-swapped.)
a61af66fc99e Initial load
duke
parents:
diff changeset
2718 scope_values->append(second);
a61af66fc99e Initial load
duke
parents:
diff changeset
2719 scope_values->append(first);
a61af66fc99e Initial load
duke
parents:
diff changeset
2720 return 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2721 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2722 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2723
a61af66fc99e Initial load
duke
parents:
diff changeset
2724
a61af66fc99e Initial load
duke
parents:
diff changeset
2725 int LinearScan::append_scope_value(int op_id, Value value, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2726 if (value != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2727 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
2728 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
2729
a61af66fc99e Initial load
duke
parents:
diff changeset
2730 assert(con == NULL || opr->is_virtual() || opr->is_constant() || opr->is_illegal(), "asumption: Constant instructions have only constant operands (or illegal if constant is optimized away)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2731 assert(con != NULL || opr->is_virtual(), "asumption: non-Constant instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2732
a61af66fc99e Initial load
duke
parents:
diff changeset
2733 if (con != NULL && !con->is_pinned() && !opr->is_constant()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2734 // Unpinned constants may have a virtual operand for a part of the lifetime
a61af66fc99e Initial load
duke
parents:
diff changeset
2735 // or may be illegal when it was optimized away,
a61af66fc99e Initial load
duke
parents:
diff changeset
2736 // so always use a constant operand
a61af66fc99e Initial load
duke
parents:
diff changeset
2737 opr = LIR_OprFact::value_type(con->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
2738 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2739 assert(opr->is_virtual() || opr->is_constant(), "other cases not allowed here");
a61af66fc99e Initial load
duke
parents:
diff changeset
2740
a61af66fc99e Initial load
duke
parents:
diff changeset
2741 if (opr->is_virtual()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2742 LIR_OpVisitState::OprMode mode = LIR_OpVisitState::inputMode;
a61af66fc99e Initial load
duke
parents:
diff changeset
2743
a61af66fc99e Initial load
duke
parents:
diff changeset
2744 BlockBegin* block = block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2745 if (block->number_of_sux() == 1 && op_id == block->last_lir_instruction_id()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2746 // generating debug information for the last instruction of a block.
a61af66fc99e Initial load
duke
parents:
diff changeset
2747 // if this instruction is a branch, spill moves are inserted before this branch
a61af66fc99e Initial load
duke
parents:
diff changeset
2748 // and so the wrong operand would be returned (spill moves at block boundaries are not
a61af66fc99e Initial load
duke
parents:
diff changeset
2749 // considered in the live ranges of intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
2750 // Solution: use the first op_id of the branch target block instead.
a61af66fc99e Initial load
duke
parents:
diff changeset
2751 if (block->lir()->instructions_list()->last()->as_OpBranch() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2752 if (block->live_out().at(opr->vreg_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2753 op_id = block->sux_at(0)->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
2754 mode = LIR_OpVisitState::outputMode;
a61af66fc99e Initial load
duke
parents:
diff changeset
2755 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2756 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2757 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2758
a61af66fc99e Initial load
duke
parents:
diff changeset
2759 // Get current location of operand
a61af66fc99e Initial load
duke
parents:
diff changeset
2760 // The operand must be live because debug information is considered when building the intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
2761 // if the interval is not live, color_lir_opr will cause an assertion failure
a61af66fc99e Initial load
duke
parents:
diff changeset
2762 opr = color_lir_opr(opr, op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2763 assert(!has_call(op_id) || opr->is_stack() || !is_caller_save(reg_num(opr)), "can not have caller-save register operands at calls");
a61af66fc99e Initial load
duke
parents:
diff changeset
2764
a61af66fc99e Initial load
duke
parents:
diff changeset
2765 // Append to ScopeValue array
a61af66fc99e Initial load
duke
parents:
diff changeset
2766 return append_scope_value_for_operand(opr, scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
2767
a61af66fc99e Initial load
duke
parents:
diff changeset
2768 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2769 assert(value->as_Constant() != NULL, "all other instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2770 assert(opr->is_constant(), "operand must be constant");
a61af66fc99e Initial load
duke
parents:
diff changeset
2771
a61af66fc99e Initial load
duke
parents:
diff changeset
2772 return append_scope_value_for_constant(opr, scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
2773 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2774 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2775 // append a dummy value because real value not needed
a61af66fc99e Initial load
duke
parents:
diff changeset
2776 scope_values->append(&_illegal_value);
a61af66fc99e Initial load
duke
parents:
diff changeset
2777 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2778 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2779 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2780
a61af66fc99e Initial load
duke
parents:
diff changeset
2781
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2782 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
2783 IRScopeDebugInfo* caller_debug_info = NULL;
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2784
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2785 ValueStack* caller_state = cur_state->caller_state();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2786 if (caller_state != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2787 // process recursively to compute outermost scope first
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2788 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
2789 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2790
a61af66fc99e Initial load
duke
parents:
diff changeset
2791 // initialize these to null.
a61af66fc99e Initial load
duke
parents:
diff changeset
2792 // If we don't need deopt info or there are no locals, expressions or monitors,
a61af66fc99e Initial load
duke
parents:
diff changeset
2793 // then these get recorded as no information and avoids the allocation of 0 length arrays.
a61af66fc99e Initial load
duke
parents:
diff changeset
2794 GrowableArray<ScopeValue*>* locals = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2795 GrowableArray<ScopeValue*>* expressions = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2796 GrowableArray<MonitorValue*>* monitors = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2797
a61af66fc99e Initial load
duke
parents:
diff changeset
2798 // describe local variable values
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2799 int nof_locals = cur_state->locals_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2800 if (nof_locals > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2801 locals = new GrowableArray<ScopeValue*>(nof_locals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2802
a61af66fc99e Initial load
duke
parents:
diff changeset
2803 int pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2804 while (pos < nof_locals) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2805 assert(pos < cur_state->locals_size(), "why not?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2806
a61af66fc99e Initial load
duke
parents:
diff changeset
2807 Value local = cur_state->local_at(pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
2808 pos += append_scope_value(op_id, local, locals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2809
a61af66fc99e Initial load
duke
parents:
diff changeset
2810 assert(locals->length() == pos, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
2811 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2812 assert(locals->length() == cur_scope->method()->max_locals(), "wrong number of locals");
a61af66fc99e Initial load
duke
parents:
diff changeset
2813 assert(locals->length() == cur_state->locals_size(), "wrong number of locals");
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2814 } else if (cur_scope->method()->max_locals() > 0) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2815 assert(cur_state->kind() == ValueStack::EmptyExceptionState, "should be");
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2816 nof_locals = cur_scope->method()->max_locals();
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2817 locals = new GrowableArray<ScopeValue*>(nof_locals);
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2818 for(int i = 0; i < nof_locals; i++) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2819 locals->append(&_illegal_value);
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2820 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2821 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2822
a61af66fc99e Initial load
duke
parents:
diff changeset
2823 // describe expression stack
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2824 int nof_stack = cur_state->stack_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2825 if (nof_stack > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2826 expressions = new GrowableArray<ScopeValue*>(nof_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
2827
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2828 int pos = 0;
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2829 while (pos < nof_stack) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2830 Value expression = cur_state->stack_at_inc(pos);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2831 append_scope_value(op_id, expression, expressions);
a61af66fc99e Initial load
duke
parents:
diff changeset
2832
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2833 assert(expressions->length() == pos, "must match");
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2834 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2835 assert(expressions->length() == cur_state->stack_size(), "wrong number of stack entries");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2836 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2837
a61af66fc99e Initial load
duke
parents:
diff changeset
2838 // describe monitors
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2839 int nof_locks = cur_state->locks_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2840 if (nof_locks > 0) {
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2841 int lock_offset = cur_state->caller_state() != NULL ? cur_state->caller_state()->total_locks_size() : 0;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2842 monitors = new GrowableArray<MonitorValue*>(nof_locks);
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2843 for (int i = 0; i < nof_locks; i++) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2844 monitors->append(location_for_monitor_index(lock_offset + i));
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2845 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2846 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2847
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2848 return new IRScopeDebugInfo(cur_scope, cur_state->bci(), locals, expressions, monitors, caller_debug_info);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2849 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2850
a61af66fc99e Initial load
duke
parents:
diff changeset
2851
a61af66fc99e Initial load
duke
parents:
diff changeset
2852 void LinearScan::compute_debug_info(CodeEmitInfo* info, int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2853 TRACE_LINEAR_SCAN(3, tty->print_cr("creating debug information at op_id %d", op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
2854
a61af66fc99e Initial load
duke
parents:
diff changeset
2855 IRScope* innermost_scope = info->scope();
a61af66fc99e Initial load
duke
parents:
diff changeset
2856 ValueStack* innermost_state = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
2857
a61af66fc99e Initial load
duke
parents:
diff changeset
2858 assert(innermost_scope != NULL && innermost_state != NULL, "why is it missing?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2859
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2860 DEBUG_ONLY(check_stack_depth(info, innermost_state->stack_size()));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2861
a61af66fc99e Initial load
duke
parents:
diff changeset
2862 if (info->_scope_debug_info == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2863 // compute debug information
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2864 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
2865 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2866 // 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
2867 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
2868 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2869 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2870
a61af66fc99e Initial load
duke
parents:
diff changeset
2871
a61af66fc99e Initial load
duke
parents:
diff changeset
2872 void LinearScan::assign_reg_num(LIR_OpList* instructions, IntervalWalker* iw) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2873 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
2874 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2875 bool has_dead = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
2876
a61af66fc99e Initial load
duke
parents:
diff changeset
2877 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2878 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
2879 if (op == NULL) { // this can happen when spill-moves are removed in eliminate_spill_moves
a61af66fc99e Initial load
duke
parents:
diff changeset
2880 has_dead = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
2881 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
2882 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2883 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
2884
a61af66fc99e Initial load
duke
parents:
diff changeset
2885 // visit instruction to get list of operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2886 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2887
a61af66fc99e Initial load
duke
parents:
diff changeset
2888 // iterate all modes of the visitor and process all virtual operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2889 for_each_visitor_mode(mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2890 int n = visitor.opr_count(mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2891 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2892 LIR_Opr opr = visitor.opr_at(mode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
2893 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2894 visitor.set_opr_at(mode, k, color_lir_opr(opr, op_id, mode));
a61af66fc99e Initial load
duke
parents:
diff changeset
2895 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2896 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2897 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2898
a61af66fc99e Initial load
duke
parents:
diff changeset
2899 if (visitor.info_count() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2900 // exception handling
a61af66fc99e Initial load
duke
parents:
diff changeset
2901 if (compilation()->has_exception_handlers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2902 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
2903 int n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2904 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2905 XHandler* handler = xhandlers->handler_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
2906 if (handler->entry_code() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2907 assign_reg_num(handler->entry_code()->instructions_list(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2908 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2909 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2910 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2911 assert(visitor.all_xhandler()->length() == 0, "missed exception handler");
a61af66fc99e Initial load
duke
parents:
diff changeset
2912 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2913
a61af66fc99e Initial load
duke
parents:
diff changeset
2914 // compute oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2915 assert(iw != NULL, "needed for compute_oop_map");
a61af66fc99e Initial load
duke
parents:
diff changeset
2916 compute_oop_map(iw, visitor, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2917
a61af66fc99e Initial load
duke
parents:
diff changeset
2918 // compute debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
2919 if (!use_fpu_stack_allocation()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2920 // compute debug information if fpu stack allocation is not needed.
a61af66fc99e Initial load
duke
parents:
diff changeset
2921 // when fpu stack allocation is needed, the debug information can not
a61af66fc99e Initial load
duke
parents:
diff changeset
2922 // be computed here because the exact location of fpu operands is not known
a61af66fc99e Initial load
duke
parents:
diff changeset
2923 // -> debug information is created inside the fpu stack allocator
a61af66fc99e Initial load
duke
parents:
diff changeset
2924 int n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
2925 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2926 compute_debug_info(visitor.info_at(k), op_id);
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
a61af66fc99e Initial load
duke
parents:
diff changeset
2931 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2932 // make sure we haven't made the op invalid.
a61af66fc99e Initial load
duke
parents:
diff changeset
2933 op->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
2934 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2935
a61af66fc99e Initial load
duke
parents:
diff changeset
2936 // remove useless moves
a61af66fc99e Initial load
duke
parents:
diff changeset
2937 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2938 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
2939 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
2940 LIR_Opr src = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2941 LIR_Opr dst = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2942 if (dst == src ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2943 !dst->is_pointer() && !src->is_pointer() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2944 src->is_same_register(dst)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2945 instructions->at_put(j, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2946 has_dead = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
2947 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2948 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2949 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2950
a61af66fc99e Initial load
duke
parents:
diff changeset
2951 if (has_dead) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2952 // iterate all instructions of the block and remove all null-values.
a61af66fc99e Initial load
duke
parents:
diff changeset
2953 int insert_point = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2954 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2955 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
2956 if (op != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2957 if (insert_point != j) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2958 instructions->at_put(insert_point, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2959 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2960 insert_point++;
a61af66fc99e Initial load
duke
parents:
diff changeset
2961 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2962 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2963 instructions->truncate(insert_point);
a61af66fc99e Initial load
duke
parents:
diff changeset
2964 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2965 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2966
a61af66fc99e Initial load
duke
parents:
diff changeset
2967 void LinearScan::assign_reg_num() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2968 TIME_LINEAR_SCAN(timer_assign_reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
2969
a61af66fc99e Initial load
duke
parents:
diff changeset
2970 init_compute_debug_info();
a61af66fc99e Initial load
duke
parents:
diff changeset
2971 IntervalWalker* iw = init_compute_oop_maps();
a61af66fc99e Initial load
duke
parents:
diff changeset
2972
a61af66fc99e Initial load
duke
parents:
diff changeset
2973 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
2974 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2975 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2976 assign_reg_num(block->lir()->instructions_list(), iw);
a61af66fc99e Initial load
duke
parents:
diff changeset
2977 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2978 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2979
a61af66fc99e Initial load
duke
parents:
diff changeset
2980
a61af66fc99e Initial load
duke
parents:
diff changeset
2981 void LinearScan::do_linear_scan() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2982 NOT_PRODUCT(_total_timer.begin_method());
a61af66fc99e Initial load
duke
parents:
diff changeset
2983
a61af66fc99e Initial load
duke
parents:
diff changeset
2984 number_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
2985
a61af66fc99e Initial load
duke
parents:
diff changeset
2986 NOT_PRODUCT(print_lir(1, "Before Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
2987
a61af66fc99e Initial load
duke
parents:
diff changeset
2988 compute_local_live_sets();
a61af66fc99e Initial load
duke
parents:
diff changeset
2989 compute_global_live_sets();
a61af66fc99e Initial load
duke
parents:
diff changeset
2990 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
2991
a61af66fc99e Initial load
duke
parents:
diff changeset
2992 build_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
2993 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
2994 sort_intervals_before_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
2995
a61af66fc99e Initial load
duke
parents:
diff changeset
2996 NOT_PRODUCT(print_intervals("Before Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
2997 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_before_alloc));
a61af66fc99e Initial load
duke
parents:
diff changeset
2998
a61af66fc99e Initial load
duke
parents:
diff changeset
2999 allocate_registers();
a61af66fc99e Initial load
duke
parents:
diff changeset
3000 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3001
a61af66fc99e Initial load
duke
parents:
diff changeset
3002 resolve_data_flow();
a61af66fc99e Initial load
duke
parents:
diff changeset
3003 if (compilation()->has_exception_handlers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3004 resolve_exception_handlers();
a61af66fc99e Initial load
duke
parents:
diff changeset
3005 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3006 // fill in number of spill slots into frame_map
a61af66fc99e Initial load
duke
parents:
diff changeset
3007 propagate_spill_slots();
a61af66fc99e Initial load
duke
parents:
diff changeset
3008 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3009
a61af66fc99e Initial load
duke
parents:
diff changeset
3010 NOT_PRODUCT(print_intervals("After Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3011 NOT_PRODUCT(print_lir(2, "LIR after register allocation:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3012
a61af66fc99e Initial load
duke
parents:
diff changeset
3013 sort_intervals_after_allocation();
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3014
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3015 DEBUG_ONLY(verify());
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3016
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3017 eliminate_spill_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
3018 assign_reg_num();
a61af66fc99e Initial load
duke
parents:
diff changeset
3019 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3020
a61af66fc99e Initial load
duke
parents:
diff changeset
3021 NOT_PRODUCT(print_lir(2, "LIR after assignment of register numbers:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3022 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_after_asign));
a61af66fc99e Initial load
duke
parents:
diff changeset
3023
a61af66fc99e Initial load
duke
parents:
diff changeset
3024 { TIME_LINEAR_SCAN(timer_allocate_fpu_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
3025
a61af66fc99e Initial load
duke
parents:
diff changeset
3026 if (use_fpu_stack_allocation()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3027 allocate_fpu_stack(); // Only has effect on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
3028 NOT_PRODUCT(print_lir(2, "LIR after FPU stack allocation:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3029 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3030 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3031
a61af66fc99e Initial load
duke
parents:
diff changeset
3032 { TIME_LINEAR_SCAN(timer_optimize_lir);
a61af66fc99e Initial load
duke
parents:
diff changeset
3033
a61af66fc99e Initial load
duke
parents:
diff changeset
3034 EdgeMoveOptimizer::optimize(ir()->code());
a61af66fc99e Initial load
duke
parents:
diff changeset
3035 ControlFlowOptimizer::optimize(ir()->code());
a61af66fc99e Initial load
duke
parents:
diff changeset
3036 // check that cfg is still correct after optimizations
a61af66fc99e Initial load
duke
parents:
diff changeset
3037 ir()->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
3038 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3039
a61af66fc99e Initial load
duke
parents:
diff changeset
3040 NOT_PRODUCT(print_lir(1, "Before Code Generation", false));
a61af66fc99e Initial load
duke
parents:
diff changeset
3041 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_final));
a61af66fc99e Initial load
duke
parents:
diff changeset
3042 NOT_PRODUCT(_total_timer.end_method(this));
a61af66fc99e Initial load
duke
parents:
diff changeset
3043 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3044
a61af66fc99e Initial load
duke
parents:
diff changeset
3045
a61af66fc99e Initial load
duke
parents:
diff changeset
3046 // ********** Printing functions
a61af66fc99e Initial load
duke
parents:
diff changeset
3047
a61af66fc99e Initial load
duke
parents:
diff changeset
3048 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
3049
a61af66fc99e Initial load
duke
parents:
diff changeset
3050 void LinearScan::print_timers(double total) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3051 _total_timer.print(total);
a61af66fc99e Initial load
duke
parents:
diff changeset
3052 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3053
a61af66fc99e Initial load
duke
parents:
diff changeset
3054 void LinearScan::print_statistics() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3055 _stat_before_alloc.print("before allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
3056 _stat_after_asign.print("after assignment of register");
a61af66fc99e Initial load
duke
parents:
diff changeset
3057 _stat_final.print("after optimization");
a61af66fc99e Initial load
duke
parents:
diff changeset
3058 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3059
a61af66fc99e Initial load
duke
parents:
diff changeset
3060 void LinearScan::print_bitmap(BitMap& b) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3061 for (unsigned int i = 0; i < b.size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3062 if (b.at(i)) tty->print("%d ", i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3063 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3064 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3065 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3066
a61af66fc99e Initial load
duke
parents:
diff changeset
3067 void LinearScan::print_intervals(const char* label) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3068 if (TraceLinearScanLevel >= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3069 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3070 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3071 tty->print_cr("%s", label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3072
a61af66fc99e Initial load
duke
parents:
diff changeset
3073 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3074 Interval* interval = interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3075 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3076 interval->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
3077 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3078 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3079
a61af66fc99e Initial load
duke
parents:
diff changeset
3080 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3081 tty->print_cr("--- Basic Blocks ---");
a61af66fc99e Initial load
duke
parents:
diff changeset
3082 for (i = 0; i < block_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3083 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3084 tty->print("B%d [%d, %d, %d, %d] ", block->block_id(), block->first_lir_instruction_id(), block->last_lir_instruction_id(), block->loop_index(), block->loop_depth());
a61af66fc99e Initial load
duke
parents:
diff changeset
3085 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3086 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3087 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3088 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3089
a61af66fc99e Initial load
duke
parents:
diff changeset
3090 if (PrintCFGToFile) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3091 CFGPrinter::print_intervals(&_intervals, label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3092 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3093 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3094
a61af66fc99e Initial load
duke
parents:
diff changeset
3095 void LinearScan::print_lir(int level, const char* label, bool hir_valid) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3096 if (TraceLinearScanLevel >= level) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3097 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3098 tty->print_cr("%s", label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3099 print_LIR(ir()->linear_scan_order());
a61af66fc99e Initial load
duke
parents:
diff changeset
3100 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3102
a61af66fc99e Initial load
duke
parents:
diff changeset
3103 if (level == 1 && PrintCFGToFile) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3104 CFGPrinter::print_cfg(ir()->linear_scan_order(), label, hir_valid, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
3105 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3106 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3107
a61af66fc99e Initial load
duke
parents:
diff changeset
3108 #endif //PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
3109
a61af66fc99e Initial load
duke
parents:
diff changeset
3110
a61af66fc99e Initial load
duke
parents:
diff changeset
3111 // ********** verification functions for allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
3112 // (check that all intervals have a correct register and that no registers are overwritten)
a61af66fc99e Initial load
duke
parents:
diff changeset
3113 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3114
a61af66fc99e Initial load
duke
parents:
diff changeset
3115 void LinearScan::verify() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3116 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying intervals ******************************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3117 verify_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3118
a61af66fc99e Initial load
duke
parents:
diff changeset
3119 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying that no oops are in fixed intervals ****************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3120 verify_no_oops_in_fixed_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3121
a61af66fc99e Initial load
duke
parents:
diff changeset
3122 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying that unpinned constants are not alive across block boundaries"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3123 verify_constants();
a61af66fc99e Initial load
duke
parents:
diff changeset
3124
a61af66fc99e Initial load
duke
parents:
diff changeset
3125 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying register allocation ********************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3126 verify_registers();
a61af66fc99e Initial load
duke
parents:
diff changeset
3127
a61af66fc99e Initial load
duke
parents:
diff changeset
3128 TRACE_LINEAR_SCAN(2, tty->print_cr("********* no errors found **********************************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3129 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3130
a61af66fc99e Initial load
duke
parents:
diff changeset
3131 void LinearScan::verify_intervals() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3132 int len = interval_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3133 bool has_error = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3134
a61af66fc99e Initial load
duke
parents:
diff changeset
3135 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3136 Interval* i1 = interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3137 if (i1 == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3138
a61af66fc99e Initial load
duke
parents:
diff changeset
3139 i1->check_split_children();
a61af66fc99e Initial load
duke
parents:
diff changeset
3140
a61af66fc99e Initial load
duke
parents:
diff changeset
3141 if (i1->reg_num() != i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3142 tty->print_cr("Interval %d is on position %d in list", i1->reg_num(), i); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3143 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3144 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3145
a61af66fc99e Initial load
duke
parents:
diff changeset
3146 if (i1->reg_num() >= LIR_OprDesc::vreg_base && i1->type() == T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3147 tty->print_cr("Interval %d has no type assigned", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3148 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3149 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3150
a61af66fc99e Initial load
duke
parents:
diff changeset
3151 if (i1->assigned_reg() == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3152 tty->print_cr("Interval %d has no register assigned", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3153 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3154 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3155
a61af66fc99e Initial load
duke
parents:
diff changeset
3156 if (i1->assigned_reg() == i1->assigned_regHi()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3157 tty->print_cr("Interval %d: low and high register equal", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3158 has_error = true;
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 (!is_processed_reg_num(i1->assigned_reg())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3162 tty->print_cr("Can not have an Interval for an ignored register"); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3163 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3164 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3165
a61af66fc99e Initial load
duke
parents:
diff changeset
3166 if (i1->first() == Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3167 tty->print_cr("Interval %d has no Range", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3168 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3169 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3170
a61af66fc99e Initial load
duke
parents:
diff changeset
3171 for (Range* r = i1->first(); r != Range::end(); r = r->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3172 if (r->from() >= r->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3173 tty->print_cr("Interval %d has zero length range", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3174 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3175 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3176 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3177
a61af66fc99e Initial load
duke
parents:
diff changeset
3178 for (int j = i + 1; j < len; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3179 Interval* i2 = interval_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3180 if (i2 == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3181
a61af66fc99e Initial load
duke
parents:
diff changeset
3182 // special intervals that are created in MoveResolver
a61af66fc99e Initial load
duke
parents:
diff changeset
3183 // -> ignore them because the range information has no meaning there
a61af66fc99e Initial load
duke
parents:
diff changeset
3184 if (i1->from() == 1 && i1->to() == 2) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3185 if (i2->from() == 1 && i2->to() == 2) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3186
a61af66fc99e Initial load
duke
parents:
diff changeset
3187 int r1 = i1->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3188 int r1Hi = i1->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3189 int r2 = i2->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3190 int r2Hi = i2->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3191 if (i1->intersects(i2) && (r1 == r2 || r1 == r2Hi || (r1Hi != any_reg && (r1Hi == r2 || r1Hi == r2Hi)))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3192 tty->print_cr("Intervals %d and %d overlap and have the same register assigned", i1->reg_num(), i2->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
3193 i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3194 i2->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3195 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3197 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3198 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3199
a61af66fc99e Initial load
duke
parents:
diff changeset
3200 assert(has_error == false, "register allocation invalid");
a61af66fc99e Initial load
duke
parents:
diff changeset
3201 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3202
a61af66fc99e Initial load
duke
parents:
diff changeset
3203
a61af66fc99e Initial load
duke
parents:
diff changeset
3204 void LinearScan::verify_no_oops_in_fixed_intervals() {
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3205 Interval* fixed_intervals;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3206 Interval* other_intervals;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3207 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
3208
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3209 // 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
3210 // with a high operation id
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3211 other_intervals = new Interval(any_reg);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3212 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
3213 IntervalWalker* iw = new IntervalWalker(this, fixed_intervals, other_intervals);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3214
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3215 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
3216 for (int i = 0; i < block_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3217 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3218
a61af66fc99e Initial load
duke
parents:
diff changeset
3219 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
3220
a61af66fc99e Initial load
duke
parents:
diff changeset
3221 for (int j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3222 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3223 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
3224
a61af66fc99e Initial load
duke
parents:
diff changeset
3225 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3226
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3227 if (visitor.info_count() > 0) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3228 iw->walk_before(op->id());
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3229 bool check_live = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3230 if (op->code() == lir_move) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3231 LIR_Op1* move = (LIR_Op1*)op;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3232 check_live = (move->patch_code() == lir_patch_none);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3233 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3234 LIR_OpBranch* branch = op->as_OpBranch();
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3235 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
3236 // 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
3237 // exception stub will never return to normal control flow.
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3238 check_live = false;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3239 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3240
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3241 // 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
3242 // oopmap since we can't handle that correctly.
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3243 if (check_live) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3244 for (Interval* interval = iw->active_first(fixedKind);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3245 interval != Interval::end();
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3246 interval = interval->next()) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3247 if (interval->current_to() > op->id() + 1) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3248 // 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
3249 // that this interval represents some value that's
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3250 // 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
3251 bool ok = false;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3252 for_each_visitor_mode(mode) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3253 int n = visitor.opr_count(mode);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3254 for (int k = 0; k < n; k++) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3255 LIR_Opr opr = visitor.opr_at(mode, k);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3256 if (opr->is_fixed_cpu()) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3257 if (interval_at(reg_num(opr)) == interval) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3258 ok = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3259 break;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3260 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3261 int hi = reg_numHi(opr);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3262 if (hi != -1 && interval_at(hi) == interval) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3263 ok = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3264 break;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3265 }
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 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3268 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3269 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
3270 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3271 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3272 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3273 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3274
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3275 // oop-maps at calls do not contain registers, so check is not needed
a61af66fc99e Initial load
duke
parents:
diff changeset
3276 if (!visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3277
a61af66fc99e Initial load
duke
parents:
diff changeset
3278 for_each_visitor_mode(mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3279 int n = visitor.opr_count(mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3280 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3281 LIR_Opr opr = visitor.opr_at(mode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
3282
a61af66fc99e Initial load
duke
parents:
diff changeset
3283 if (opr->is_fixed_cpu() && opr->is_oop()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3284 // operand is a non-virtual cpu register and contains an oop
a61af66fc99e Initial load
duke
parents:
diff changeset
3285 TRACE_LINEAR_SCAN(4, op->print_on(tty); tty->print("checking operand "); opr->print(); tty->cr());
a61af66fc99e Initial load
duke
parents:
diff changeset
3286
a61af66fc99e Initial load
duke
parents:
diff changeset
3287 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3288 assert(interval != NULL, "no interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
3289
a61af66fc99e Initial load
duke
parents:
diff changeset
3290 if (mode == LIR_OpVisitState::inputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3291 if (interval->to() >= op_id + 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3292 assert(interval->to() < op_id + 2 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
3293 interval->has_hole_between(op_id, op_id + 2),
a61af66fc99e Initial load
duke
parents:
diff changeset
3294 "oop input operand live after instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
3295 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3296 } else if (mode == LIR_OpVisitState::outputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3297 if (interval->from() <= op_id - 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3298 assert(interval->has_hole_between(op_id - 1, op_id),
a61af66fc99e Initial load
duke
parents:
diff changeset
3299 "oop input operand live after instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
3300 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3301 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3302 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3303 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3304 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3305 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3306 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3307 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3308 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3309
a61af66fc99e Initial load
duke
parents:
diff changeset
3310
a61af66fc99e Initial load
duke
parents:
diff changeset
3311 void LinearScan::verify_constants() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3312 int num_regs = num_virtual_regs();
a61af66fc99e Initial load
duke
parents:
diff changeset
3313 int size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
3314 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3315
a61af66fc99e Initial load
duke
parents:
diff changeset
3316 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3317 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3318 BitMap live_at_edge = block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
3319
a61af66fc99e Initial load
duke
parents:
diff changeset
3320 // 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
3321 for (int r = (int)live_at_edge.get_next_one_offset(0, size); r < size; r = (int)live_at_edge.get_next_one_offset(r + 1, size)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3322 TRACE_LINEAR_SCAN(4, tty->print("checking interval %d of block B%d", r, block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3323
a61af66fc99e Initial load
duke
parents:
diff changeset
3324 Value value = gen()->instruction_for_vreg(r);
a61af66fc99e Initial load
duke
parents:
diff changeset
3325
a61af66fc99e Initial load
duke
parents:
diff changeset
3326 assert(value != NULL, "all intervals live across block boundaries must have Value");
a61af66fc99e Initial load
duke
parents:
diff changeset
3327 assert(value->operand()->is_register() && value->operand()->is_virtual(), "value must have virtual operand");
a61af66fc99e Initial load
duke
parents:
diff changeset
3328 assert(value->operand()->vreg_number() == r, "register number must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
3329 // TKR assert(value->as_Constant() == NULL || value->is_pinned(), "only pinned constants can be alive accross block boundaries");
a61af66fc99e Initial load
duke
parents:
diff changeset
3330 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3331 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3332 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3333
a61af66fc99e Initial load
duke
parents:
diff changeset
3334
a61af66fc99e Initial load
duke
parents:
diff changeset
3335 class RegisterVerifier: public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
3336 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
3337 LinearScan* _allocator;
a61af66fc99e Initial load
duke
parents:
diff changeset
3338 BlockList _work_list; // all blocks that must be processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3339 IntervalsList _saved_states; // saved information of previous check
a61af66fc99e Initial load
duke
parents:
diff changeset
3340
a61af66fc99e Initial load
duke
parents:
diff changeset
3341 // simplified access to methods of LinearScan
a61af66fc99e Initial load
duke
parents:
diff changeset
3342 Compilation* compilation() const { return _allocator->compilation(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3343 Interval* interval_at(int reg_num) const { return _allocator->interval_at(reg_num); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3344 int reg_num(LIR_Opr opr) const { return _allocator->reg_num(opr); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3345
a61af66fc99e Initial load
duke
parents:
diff changeset
3346 // currently, only registers are processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3347 int state_size() { return LinearScan::nof_regs; }
a61af66fc99e Initial load
duke
parents:
diff changeset
3348
a61af66fc99e Initial load
duke
parents:
diff changeset
3349 // accessors
a61af66fc99e Initial load
duke
parents:
diff changeset
3350 IntervalList* state_for_block(BlockBegin* block) { return _saved_states.at(block->block_id()); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3351 void set_state_for_block(BlockBegin* block, IntervalList* saved_state) { _saved_states.at_put(block->block_id(), saved_state); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3352 void add_to_work_list(BlockBegin* block) { if (!_work_list.contains(block)) _work_list.append(block); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3353
a61af66fc99e Initial load
duke
parents:
diff changeset
3354 // helper functions
a61af66fc99e Initial load
duke
parents:
diff changeset
3355 IntervalList* copy(IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3356 void state_put(IntervalList* input_state, int reg, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3357 bool check_state(IntervalList* input_state, int reg, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3358
a61af66fc99e Initial load
duke
parents:
diff changeset
3359 void process_block(BlockBegin* block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3360 void process_xhandler(XHandler* xhandler, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3361 void process_successor(BlockBegin* block, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3362 void process_operations(LIR_List* ops, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3363
a61af66fc99e Initial load
duke
parents:
diff changeset
3364 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
3365 RegisterVerifier(LinearScan* allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
3366 : _allocator(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
3367 , _work_list(16)
a61af66fc99e Initial load
duke
parents:
diff changeset
3368 , _saved_states(BlockBegin::number_of_blocks(), NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
3369 { }
a61af66fc99e Initial load
duke
parents:
diff changeset
3370
a61af66fc99e Initial load
duke
parents:
diff changeset
3371 void verify(BlockBegin* start);
a61af66fc99e Initial load
duke
parents:
diff changeset
3372 };
a61af66fc99e Initial load
duke
parents:
diff changeset
3373
a61af66fc99e Initial load
duke
parents:
diff changeset
3374
a61af66fc99e Initial load
duke
parents:
diff changeset
3375 // entry function from LinearScan that starts the verification
a61af66fc99e Initial load
duke
parents:
diff changeset
3376 void LinearScan::verify_registers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3377 RegisterVerifier verifier(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
3378 verifier.verify(block_at(0));
a61af66fc99e Initial load
duke
parents:
diff changeset
3379 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3380
a61af66fc99e Initial load
duke
parents:
diff changeset
3381
a61af66fc99e Initial load
duke
parents:
diff changeset
3382 void RegisterVerifier::verify(BlockBegin* start) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3383 // setup input registers (method arguments) for first block
a61af66fc99e Initial load
duke
parents:
diff changeset
3384 IntervalList* input_state = new IntervalList(state_size(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3385 CallingConvention* args = compilation()->frame_map()->incoming_arguments();
a61af66fc99e Initial load
duke
parents:
diff changeset
3386 for (int n = 0; n < args->length(); n++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3387 LIR_Opr opr = args->at(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
3388 if (opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3389 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3390
a61af66fc99e Initial load
duke
parents:
diff changeset
3391 if (interval->assigned_reg() < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3392 input_state->at_put(interval->assigned_reg(), interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3393 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3394 if (interval->assigned_regHi() != LinearScan::any_reg && interval->assigned_regHi() < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3395 input_state->at_put(interval->assigned_regHi(), interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3396 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3397 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3398 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3399
a61af66fc99e Initial load
duke
parents:
diff changeset
3400 set_state_for_block(start, input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3401 add_to_work_list(start);
a61af66fc99e Initial load
duke
parents:
diff changeset
3402
a61af66fc99e Initial load
duke
parents:
diff changeset
3403 // main loop for verification
a61af66fc99e Initial load
duke
parents:
diff changeset
3404 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
3405 BlockBegin* block = _work_list.at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
3406 _work_list.remove_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
3407
a61af66fc99e Initial load
duke
parents:
diff changeset
3408 process_block(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3409 } while (!_work_list.is_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3410 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3411
a61af66fc99e Initial load
duke
parents:
diff changeset
3412 void RegisterVerifier::process_block(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3413 TRACE_LINEAR_SCAN(2, tty->cr(); tty->print_cr("process_block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3414
a61af66fc99e Initial load
duke
parents:
diff changeset
3415 // must copy state because it is modified
a61af66fc99e Initial load
duke
parents:
diff changeset
3416 IntervalList* input_state = copy(state_for_block(block));
a61af66fc99e Initial load
duke
parents:
diff changeset
3417
a61af66fc99e Initial load
duke
parents:
diff changeset
3418 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3419 tty->print_cr("Input-State of intervals:");
a61af66fc99e Initial load
duke
parents:
diff changeset
3420 tty->print(" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
3421 for (int i = 0; i < state_size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3422 if (input_state->at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3423 tty->print(" %4d", input_state->at(i)->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
3424 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3425 tty->print(" __");
a61af66fc99e Initial load
duke
parents:
diff changeset
3426 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3427 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3428 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3429 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3430 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3431
a61af66fc99e Initial load
duke
parents:
diff changeset
3432 // process all operations of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
3433 process_operations(block->lir(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3434
a61af66fc99e Initial load
duke
parents:
diff changeset
3435 // iterate all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
3436 for (int i = 0; i < block->number_of_sux(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3437 process_successor(block->sux_at(i), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3438 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3439 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3440
a61af66fc99e Initial load
duke
parents:
diff changeset
3441 void RegisterVerifier::process_xhandler(XHandler* xhandler, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3442 TRACE_LINEAR_SCAN(2, tty->print_cr("process_xhandler B%d", xhandler->entry_block()->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3443
a61af66fc99e Initial load
duke
parents:
diff changeset
3444 // must copy state because it is modified
a61af66fc99e Initial load
duke
parents:
diff changeset
3445 input_state = copy(input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3446
a61af66fc99e Initial load
duke
parents:
diff changeset
3447 if (xhandler->entry_code() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3448 process_operations(xhandler->entry_code(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3449 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3450 process_successor(xhandler->entry_block(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3451 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3452
a61af66fc99e Initial load
duke
parents:
diff changeset
3453 void RegisterVerifier::process_successor(BlockBegin* block, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3454 IntervalList* saved_state = state_for_block(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3455
a61af66fc99e Initial load
duke
parents:
diff changeset
3456 if (saved_state != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3457 // this block was already processed before.
a61af66fc99e Initial load
duke
parents:
diff changeset
3458 // check if new input_state is consistent with saved_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3459
a61af66fc99e Initial load
duke
parents:
diff changeset
3460 bool saved_state_correct = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3461 for (int i = 0; i < state_size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3462 if (input_state->at(i) != saved_state->at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3463 // current input_state and previous saved_state assume a different
a61af66fc99e Initial load
duke
parents:
diff changeset
3464 // interval in this register -> assume that this register is invalid
a61af66fc99e Initial load
duke
parents:
diff changeset
3465 if (saved_state->at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3466 // invalidate old calculation only if it assumed that
a61af66fc99e Initial load
duke
parents:
diff changeset
3467 // register was valid. when the register was already invalid,
a61af66fc99e Initial load
duke
parents:
diff changeset
3468 // then the old calculation was correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
3469 saved_state_correct = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3470 saved_state->at_put(i, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3471
a61af66fc99e Initial load
duke
parents:
diff changeset
3472 TRACE_LINEAR_SCAN(4, tty->print_cr("process_successor B%d: invalidating slot %d", block->block_id(), i));
a61af66fc99e Initial load
duke
parents:
diff changeset
3473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3474 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3475 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3476
a61af66fc99e Initial load
duke
parents:
diff changeset
3477 if (saved_state_correct) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3478 // already processed block with correct input_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3479 TRACE_LINEAR_SCAN(2, tty->print_cr("process_successor B%d: previous visit already correct", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3480 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3481 // must re-visit this block
a61af66fc99e Initial load
duke
parents:
diff changeset
3482 TRACE_LINEAR_SCAN(2, tty->print_cr("process_successor B%d: must re-visit because input state changed", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3483 add_to_work_list(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3484 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3485
a61af66fc99e Initial load
duke
parents:
diff changeset
3486 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3487 // block was not processed before, so set initial input_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3488 TRACE_LINEAR_SCAN(2, tty->print_cr("process_successor B%d: initial visit", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3489
a61af66fc99e Initial load
duke
parents:
diff changeset
3490 set_state_for_block(block, copy(input_state));
a61af66fc99e Initial load
duke
parents:
diff changeset
3491 add_to_work_list(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3492 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3493 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3494
a61af66fc99e Initial load
duke
parents:
diff changeset
3495
a61af66fc99e Initial load
duke
parents:
diff changeset
3496 IntervalList* RegisterVerifier::copy(IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3497 IntervalList* copy_state = new IntervalList(input_state->length());
a61af66fc99e Initial load
duke
parents:
diff changeset
3498 copy_state->push_all(input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3499 return copy_state;
a61af66fc99e Initial load
duke
parents:
diff changeset
3500 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3501
a61af66fc99e Initial load
duke
parents:
diff changeset
3502 void RegisterVerifier::state_put(IntervalList* input_state, int reg, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3503 if (reg != LinearScan::any_reg && reg < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3504 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3505 TRACE_LINEAR_SCAN(4, tty->print_cr(" reg[%d] = %d", reg, interval->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3506 } else if (input_state->at(reg) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3507 TRACE_LINEAR_SCAN(4, tty->print_cr(" reg[%d] = NULL", reg));
a61af66fc99e Initial load
duke
parents:
diff changeset
3508 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3509
a61af66fc99e Initial load
duke
parents:
diff changeset
3510 input_state->at_put(reg, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3511 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3512 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3513
a61af66fc99e Initial load
duke
parents:
diff changeset
3514 bool RegisterVerifier::check_state(IntervalList* input_state, int reg, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3515 if (reg != LinearScan::any_reg && reg < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3516 if (input_state->at(reg) != interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3517 tty->print_cr("!! Error in register allocation: register %d does not contain interval %d", reg, interval->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
3518 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3519 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3520 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3521 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3522 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3523
a61af66fc99e Initial load
duke
parents:
diff changeset
3524 void RegisterVerifier::process_operations(LIR_List* ops, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3525 // visit all instructions of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
3526 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
3527 bool has_error = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3528
a61af66fc99e Initial load
duke
parents:
diff changeset
3529 for (int i = 0; i < ops->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3530 LIR_Op* op = ops->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3531 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3532
a61af66fc99e Initial load
duke
parents:
diff changeset
3533 TRACE_LINEAR_SCAN(4, op->print_on(tty));
a61af66fc99e Initial load
duke
parents:
diff changeset
3534
a61af66fc99e Initial load
duke
parents:
diff changeset
3535 // check if input operands are correct
a61af66fc99e Initial load
duke
parents:
diff changeset
3536 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
3537 int n = visitor.opr_count(LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3538 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3539 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3540 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3541 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3542 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3543 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3544 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3545
a61af66fc99e Initial load
duke
parents:
diff changeset
3546 has_error |= check_state(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3547 has_error |= check_state(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3548
a61af66fc99e Initial load
duke
parents:
diff changeset
3549 // When an operand is marked with is_last_use, then the fpu stack allocator
a61af66fc99e Initial load
duke
parents:
diff changeset
3550 // removes the register from the fpu stack -> the register contains no value
a61af66fc99e Initial load
duke
parents:
diff changeset
3551 if (opr->is_last_use()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3552 state_put(input_state, interval->assigned_reg(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3553 state_put(input_state, interval->assigned_regHi(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3554 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3555 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3556 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3557
a61af66fc99e Initial load
duke
parents:
diff changeset
3558 // invalidate all caller save registers at calls
a61af66fc99e Initial load
duke
parents:
diff changeset
3559 if (visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3560 for (j = 0; j < FrameMap::nof_caller_save_cpu_regs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3561 state_put(input_state, reg_num(FrameMap::caller_save_cpu_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3562 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3563 for (j = 0; j < FrameMap::nof_caller_save_fpu_regs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3564 state_put(input_state, reg_num(FrameMap::caller_save_fpu_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3565 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3566
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
3567 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3568 for (j = 0; j < FrameMap::nof_caller_save_xmm_regs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3569 state_put(input_state, reg_num(FrameMap::caller_save_xmm_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3571 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
3572 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3573
a61af66fc99e Initial load
duke
parents:
diff changeset
3574 // process xhandler before output and temp operands
a61af66fc99e Initial load
duke
parents:
diff changeset
3575 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
3576 n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
3577 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3578 process_xhandler(xhandlers->handler_at(k), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3579 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3580
a61af66fc99e Initial load
duke
parents:
diff changeset
3581 // set temp operands (some operations use temp operands also as output operands, so can't set them NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
3582 n = visitor.opr_count(LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3583 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3584 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3585 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3586 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3587 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3588 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3589 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3590
a61af66fc99e Initial load
duke
parents:
diff changeset
3591 state_put(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3592 state_put(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3593 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3595
a61af66fc99e Initial load
duke
parents:
diff changeset
3596 // set output operands
a61af66fc99e Initial load
duke
parents:
diff changeset
3597 n = visitor.opr_count(LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3598 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3599 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3600 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3601 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3602 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3603 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3604 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3605
a61af66fc99e Initial load
duke
parents:
diff changeset
3606 state_put(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3607 state_put(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3608 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3609 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3610 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3611 assert(has_error == false, "Error in register allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
3612 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3613
a61af66fc99e Initial load
duke
parents:
diff changeset
3614 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3615
a61af66fc99e Initial load
duke
parents:
diff changeset
3616
a61af66fc99e Initial load
duke
parents:
diff changeset
3617
a61af66fc99e Initial load
duke
parents:
diff changeset
3618 // **** Implementation of MoveResolver ******************************
a61af66fc99e Initial load
duke
parents:
diff changeset
3619
a61af66fc99e Initial load
duke
parents:
diff changeset
3620 MoveResolver::MoveResolver(LinearScan* allocator) :
a61af66fc99e Initial load
duke
parents:
diff changeset
3621 _allocator(allocator),
a61af66fc99e Initial load
duke
parents:
diff changeset
3622 _multiple_reads_allowed(false),
a61af66fc99e Initial load
duke
parents:
diff changeset
3623 _mapping_from(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3624 _mapping_from_opr(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3625 _mapping_to(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3626 _insert_list(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
3627 _insert_idx(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
3628 _insertion_buffer()
a61af66fc99e Initial load
duke
parents:
diff changeset
3629 {
a61af66fc99e Initial load
duke
parents:
diff changeset
3630 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3631 _register_blocked[i] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
3632 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3633 DEBUG_ONLY(check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3634 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3635
a61af66fc99e Initial load
duke
parents:
diff changeset
3636
a61af66fc99e Initial load
duke
parents:
diff changeset
3637 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3638
a61af66fc99e Initial load
duke
parents:
diff changeset
3639 void MoveResolver::check_empty() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3640 assert(_mapping_from.length() == 0 && _mapping_from_opr.length() == 0 && _mapping_to.length() == 0, "list must be empty before and after processing");
a61af66fc99e Initial load
duke
parents:
diff changeset
3641 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3642 assert(register_blocked(i) == 0, "register map must be empty before and after processing");
a61af66fc99e Initial load
duke
parents:
diff changeset
3643 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3644 assert(_multiple_reads_allowed == false, "must have default value");
a61af66fc99e Initial load
duke
parents:
diff changeset
3645 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3646
a61af66fc99e Initial load
duke
parents:
diff changeset
3647 void MoveResolver::verify_before_resolve() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3648 assert(_mapping_from.length() == _mapping_from_opr.length(), "length must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3649 assert(_mapping_from.length() == _mapping_to.length(), "length must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3650 assert(_insert_list != NULL && _insert_idx != -1, "insert position not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
3651
a61af66fc99e Initial load
duke
parents:
diff changeset
3652 int i, j;
a61af66fc99e Initial load
duke
parents:
diff changeset
3653 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3654 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3655 for (j = i + 1; j < _mapping_from.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3656 assert(_mapping_from.at(i) == NULL || _mapping_from.at(i) != _mapping_from.at(j), "cannot read from same interval twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3657 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3658 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3659 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3660
a61af66fc99e Initial load
duke
parents:
diff changeset
3661 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3662 for (j = i + 1; j < _mapping_to.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3663 assert(_mapping_to.at(i) != _mapping_to.at(j), "cannot write to same interval twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3664 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3665 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3666
a61af66fc99e Initial load
duke
parents:
diff changeset
3667
a61af66fc99e Initial load
duke
parents:
diff changeset
3668 BitMap used_regs(LinearScan::nof_regs + allocator()->frame_map()->argcount() + allocator()->max_spills());
a61af66fc99e Initial load
duke
parents:
diff changeset
3669 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3670 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3671 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3672 Interval* it = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3673 if (it != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3674 assert(!used_regs.at(it->assigned_reg()), "cannot read from same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3675 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3676
a61af66fc99e Initial load
duke
parents:
diff changeset
3677 if (it->assigned_regHi() != LinearScan::any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3678 assert(!used_regs.at(it->assigned_regHi()), "cannot read from same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3679 used_regs.set_bit(it->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
3680 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3681 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3682 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3683 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3684
a61af66fc99e Initial load
duke
parents:
diff changeset
3685 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3686 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3687 Interval* it = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3688 assert(!used_regs.at(it->assigned_reg()), "cannot write to same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3689 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3690
a61af66fc99e Initial load
duke
parents:
diff changeset
3691 if (it->assigned_regHi() != LinearScan::any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3692 assert(!used_regs.at(it->assigned_regHi()), "cannot write to same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3693 used_regs.set_bit(it->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
3694 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3695 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3696
a61af66fc99e Initial load
duke
parents:
diff changeset
3697 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3698 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3699 Interval* it = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3700 if (it != NULL && it->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3701 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3702 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3703 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3704 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3705 Interval* it = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3706 assert(!used_regs.at(it->assigned_reg()) || it->assigned_reg() == _mapping_from.at(i)->assigned_reg(), "stack slots used in _mapping_from must be disjoint to _mapping_to");
a61af66fc99e Initial load
duke
parents:
diff changeset
3707 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3708 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3709
a61af66fc99e Initial load
duke
parents:
diff changeset
3710 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3711
a61af66fc99e Initial load
duke
parents:
diff changeset
3712
a61af66fc99e Initial load
duke
parents:
diff changeset
3713 // mark assigned_reg and assigned_regHi of the interval as blocked
a61af66fc99e Initial load
duke
parents:
diff changeset
3714 void MoveResolver::block_registers(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3715 int reg = it->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3716 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3717 assert(_multiple_reads_allowed || register_blocked(reg) == 0, "register already marked as used");
a61af66fc99e Initial load
duke
parents:
diff changeset
3718 set_register_blocked(reg, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3719 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3720 reg = it->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3721 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3722 assert(_multiple_reads_allowed || register_blocked(reg) == 0, "register already marked as used");
a61af66fc99e Initial load
duke
parents:
diff changeset
3723 set_register_blocked(reg, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3724 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3725 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3726
a61af66fc99e Initial load
duke
parents:
diff changeset
3727 // mark assigned_reg and assigned_regHi of the interval as unblocked
a61af66fc99e Initial load
duke
parents:
diff changeset
3728 void MoveResolver::unblock_registers(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3729 int reg = it->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3730 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3731 assert(register_blocked(reg) > 0, "register already marked as unused");
a61af66fc99e Initial load
duke
parents:
diff changeset
3732 set_register_blocked(reg, -1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3733 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3734 reg = it->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3735 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3736 assert(register_blocked(reg) > 0, "register already marked as unused");
a61af66fc99e Initial load
duke
parents:
diff changeset
3737 set_register_blocked(reg, -1);
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 // 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
3742 bool MoveResolver::save_to_process_move(Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3743 int from_reg = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3744 int from_regHi = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3745 if (from != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3746 from_reg = from->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3747 from_regHi = from->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3748 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3749
a61af66fc99e Initial load
duke
parents:
diff changeset
3750 int reg = to->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3751 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3752 if (register_blocked(reg) > 1 || (register_blocked(reg) == 1 && reg != from_reg && reg != from_regHi)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3753 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3754 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3755 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3756 reg = to->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3757 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3758 if (register_blocked(reg) > 1 || (register_blocked(reg) == 1 && reg != from_reg && reg != from_regHi)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3759 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3760 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3761 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3762
a61af66fc99e Initial load
duke
parents:
diff changeset
3763 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3764 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3765
a61af66fc99e Initial load
duke
parents:
diff changeset
3766
a61af66fc99e Initial load
duke
parents:
diff changeset
3767 void MoveResolver::create_insertion_buffer(LIR_List* list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3768 assert(!_insertion_buffer.initialized(), "overwriting existing buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3769 _insertion_buffer.init(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3770 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3771
a61af66fc99e Initial load
duke
parents:
diff changeset
3772 void MoveResolver::append_insertion_buffer() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3773 if (_insertion_buffer.initialized()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3774 _insertion_buffer.lir_list()->append(&_insertion_buffer);
a61af66fc99e Initial load
duke
parents:
diff changeset
3775 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3776 assert(!_insertion_buffer.initialized(), "must be uninitialized now");
a61af66fc99e Initial load
duke
parents:
diff changeset
3777
a61af66fc99e Initial load
duke
parents:
diff changeset
3778 _insert_list = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
3779 _insert_idx = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3780 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3781
a61af66fc99e Initial load
duke
parents:
diff changeset
3782 void MoveResolver::insert_move(Interval* from_interval, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3783 assert(from_interval->reg_num() != to_interval->reg_num(), "from and to interval equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3784 assert(from_interval->type() == to_interval->type(), "move between different types");
a61af66fc99e Initial load
duke
parents:
diff changeset
3785 assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
a61af66fc99e Initial load
duke
parents:
diff changeset
3786 assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3787
a61af66fc99e Initial load
duke
parents:
diff changeset
3788 LIR_Opr from_opr = LIR_OprFact::virtual_register(from_interval->reg_num(), from_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3789 LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3790
a61af66fc99e Initial load
duke
parents:
diff changeset
3791 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3792 // the last_use flag is an optimization for FPU stack allocation. When the same
a61af66fc99e Initial load
duke
parents:
diff changeset
3793 // input interval is used in more than one move, then it is too difficult to determine
a61af66fc99e Initial load
duke
parents:
diff changeset
3794 // if this move is really the last use.
a61af66fc99e Initial load
duke
parents:
diff changeset
3795 from_opr = from_opr->make_last_use();
a61af66fc99e Initial load
duke
parents:
diff changeset
3796 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3797 _insertion_buffer.move(_insert_idx, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3798
a61af66fc99e Initial load
duke
parents:
diff changeset
3799 TRACE_LINEAR_SCAN(4, tty->print_cr("MoveResolver: inserted move from register %d (%d, %d) to %d (%d, %d)", from_interval->reg_num(), from_interval->assigned_reg(), from_interval->assigned_regHi(), to_interval->reg_num(), to_interval->assigned_reg(), to_interval->assigned_regHi()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3800 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3801
a61af66fc99e Initial load
duke
parents:
diff changeset
3802 void MoveResolver::insert_move(LIR_Opr from_opr, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3803 assert(from_opr->type() == to_interval->type(), "move between different types");
a61af66fc99e Initial load
duke
parents:
diff changeset
3804 assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
a61af66fc99e Initial load
duke
parents:
diff changeset
3805 assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3806
a61af66fc99e Initial load
duke
parents:
diff changeset
3807 LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3808 _insertion_buffer.move(_insert_idx, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3809
a61af66fc99e Initial load
duke
parents:
diff changeset
3810 TRACE_LINEAR_SCAN(4, tty->print("MoveResolver: inserted move from constant "); from_opr->print(); tty->print_cr(" to %d (%d, %d)", to_interval->reg_num(), to_interval->assigned_reg(), to_interval->assigned_regHi()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3811 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3812
a61af66fc99e Initial load
duke
parents:
diff changeset
3813
a61af66fc99e Initial load
duke
parents:
diff changeset
3814 void MoveResolver::resolve_mappings() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3815 TRACE_LINEAR_SCAN(4, tty->print_cr("MoveResolver: resolving mappings for Block B%d, index %d", _insert_list->block() != NULL ? _insert_list->block()->block_id() : -1, _insert_idx));
a61af66fc99e Initial load
duke
parents:
diff changeset
3816 DEBUG_ONLY(verify_before_resolve());
a61af66fc99e Initial load
duke
parents:
diff changeset
3817
a61af66fc99e Initial load
duke
parents:
diff changeset
3818 // Block all registers that are used as input operands of a move.
a61af66fc99e Initial load
duke
parents:
diff changeset
3819 // When a register is blocked, no move to this register is emitted.
a61af66fc99e Initial load
duke
parents:
diff changeset
3820 // This is necessary for detecting cycles in moves.
a61af66fc99e Initial load
duke
parents:
diff changeset
3821 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3822 for (i = _mapping_from.length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3823 Interval* from_interval = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3824 if (from_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3825 block_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3826 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3827 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3828
a61af66fc99e Initial load
duke
parents:
diff changeset
3829 int spill_candidate = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3830 while (_mapping_from.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3831 bool processed_interval = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3832
a61af66fc99e Initial load
duke
parents:
diff changeset
3833 for (i = _mapping_from.length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3834 Interval* from_interval = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3835 Interval* to_interval = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3836
a61af66fc99e Initial load
duke
parents:
diff changeset
3837 if (save_to_process_move(from_interval, to_interval)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3838 // this inverval can be processed because target is free
a61af66fc99e Initial load
duke
parents:
diff changeset
3839 if (from_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3840 insert_move(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3841 unblock_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3842 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3843 insert_move(_mapping_from_opr.at(i), to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3844 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3845 _mapping_from.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3846 _mapping_from_opr.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3847 _mapping_to.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3848
a61af66fc99e Initial load
duke
parents:
diff changeset
3849 processed_interval = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3850 } else if (from_interval != NULL && from_interval->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3851 // this interval cannot be processed now because target is not free
a61af66fc99e Initial load
duke
parents:
diff changeset
3852 // it starts in a register, so it is a possible candidate for spilling
a61af66fc99e Initial load
duke
parents:
diff changeset
3853 spill_candidate = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3854 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3855 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3856
a61af66fc99e Initial load
duke
parents:
diff changeset
3857 if (!processed_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3858 // no move could be processed because there is a cycle in the move list
a61af66fc99e Initial load
duke
parents:
diff changeset
3859 // (e.g. r1 -> r2, r2 -> r1), so one interval must be spilled to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
3860 assert(spill_candidate != -1, "no interval in register for spilling found");
a61af66fc99e Initial load
duke
parents:
diff changeset
3861
a61af66fc99e Initial load
duke
parents:
diff changeset
3862 // create a new spill interval and assign a stack slot to it
a61af66fc99e Initial load
duke
parents:
diff changeset
3863 Interval* from_interval = _mapping_from.at(spill_candidate);
a61af66fc99e Initial load
duke
parents:
diff changeset
3864 Interval* spill_interval = new Interval(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3865 spill_interval->set_type(from_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3866
a61af66fc99e Initial load
duke
parents:
diff changeset
3867 // add a dummy range because real position is difficult to calculate
a61af66fc99e Initial load
duke
parents:
diff changeset
3868 // Note: this range is a special case when the integrity of the allocation is checked
a61af66fc99e Initial load
duke
parents:
diff changeset
3869 spill_interval->add_range(1, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
3870
a61af66fc99e Initial load
duke
parents:
diff changeset
3871 // do not allocate a new spill slot for temporary interval, but
a61af66fc99e Initial load
duke
parents:
diff changeset
3872 // use spill slot assigned to from_interval. Otherwise moves from
a61af66fc99e Initial load
duke
parents:
diff changeset
3873 // one stack slot to another can happen (not allowed by LIR_Assembler
a61af66fc99e Initial load
duke
parents:
diff changeset
3874 int spill_slot = from_interval->canonical_spill_slot();
a61af66fc99e Initial load
duke
parents:
diff changeset
3875 if (spill_slot < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3876 spill_slot = allocator()->allocate_spill_slot(type2spill_size[spill_interval->type()] == 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
3877 from_interval->set_canonical_spill_slot(spill_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
3878 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3879 spill_interval->assign_reg(spill_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
3880 allocator()->append_interval(spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3881
a61af66fc99e Initial load
duke
parents:
diff changeset
3882 TRACE_LINEAR_SCAN(4, tty->print_cr("created new Interval %d for spilling", spill_interval->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3883
a61af66fc99e Initial load
duke
parents:
diff changeset
3884 // insert a move from register to stack and update the mapping
a61af66fc99e Initial load
duke
parents:
diff changeset
3885 insert_move(from_interval, spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3886 _mapping_from.at_put(spill_candidate, spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3887 unblock_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3888 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3889 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3890
a61af66fc99e Initial load
duke
parents:
diff changeset
3891 // reset to default value
a61af66fc99e Initial load
duke
parents:
diff changeset
3892 _multiple_reads_allowed = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3893
a61af66fc99e Initial load
duke
parents:
diff changeset
3894 // check that all intervals have been processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3895 DEBUG_ONLY(check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3896 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3897
a61af66fc99e Initial load
duke
parents:
diff changeset
3898
a61af66fc99e Initial load
duke
parents:
diff changeset
3899 void MoveResolver::set_insert_position(LIR_List* insert_list, int insert_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3900 TRACE_LINEAR_SCAN(4, tty->print_cr("MoveResolver: setting insert position to Block B%d, index %d", insert_list->block() != NULL ? insert_list->block()->block_id() : -1, insert_idx));
a61af66fc99e Initial load
duke
parents:
diff changeset
3901 assert(_insert_list == NULL && _insert_idx == -1, "use move_insert_position instead of set_insert_position when data already set");
a61af66fc99e Initial load
duke
parents:
diff changeset
3902
a61af66fc99e Initial load
duke
parents:
diff changeset
3903 create_insertion_buffer(insert_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3904 _insert_list = insert_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
3905 _insert_idx = insert_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
3906 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3907
a61af66fc99e Initial load
duke
parents:
diff changeset
3908 void MoveResolver::move_insert_position(LIR_List* insert_list, int insert_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3909 TRACE_LINEAR_SCAN(4, tty->print_cr("MoveResolver: moving insert position to Block B%d, index %d", insert_list->block() != NULL ? insert_list->block()->block_id() : -1, insert_idx));
a61af66fc99e Initial load
duke
parents:
diff changeset
3910
a61af66fc99e Initial load
duke
parents:
diff changeset
3911 if (_insert_list != NULL && (insert_list != _insert_list || insert_idx != _insert_idx)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3912 // insert position changed -> resolve current mappings
a61af66fc99e Initial load
duke
parents:
diff changeset
3913 resolve_mappings();
a61af66fc99e Initial load
duke
parents:
diff changeset
3914 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3915
a61af66fc99e Initial load
duke
parents:
diff changeset
3916 if (insert_list != _insert_list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3917 // block changed -> append insertion_buffer because it is
a61af66fc99e Initial load
duke
parents:
diff changeset
3918 // bound to a specific block and create a new insertion_buffer
a61af66fc99e Initial load
duke
parents:
diff changeset
3919 append_insertion_buffer();
a61af66fc99e Initial load
duke
parents:
diff changeset
3920 create_insertion_buffer(insert_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3921 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3922
a61af66fc99e Initial load
duke
parents:
diff changeset
3923 _insert_list = insert_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
3924 _insert_idx = insert_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
3925 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3926
a61af66fc99e Initial load
duke
parents:
diff changeset
3927 void MoveResolver::add_mapping(Interval* from_interval, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3928 TRACE_LINEAR_SCAN(4, tty->print_cr("MoveResolver: adding mapping from %d (%d, %d) to %d (%d, %d)", from_interval->reg_num(), from_interval->assigned_reg(), from_interval->assigned_regHi(), to_interval->reg_num(), to_interval->assigned_reg(), to_interval->assigned_regHi()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3929
a61af66fc99e Initial load
duke
parents:
diff changeset
3930 _mapping_from.append(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3931 _mapping_from_opr.append(LIR_OprFact::illegalOpr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3932 _mapping_to.append(to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3933 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3934
a61af66fc99e Initial load
duke
parents:
diff changeset
3935
a61af66fc99e Initial load
duke
parents:
diff changeset
3936 void MoveResolver::add_mapping(LIR_Opr from_opr, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3937 TRACE_LINEAR_SCAN(4, tty->print("MoveResolver: adding mapping from "); from_opr->print(); tty->print_cr(" to %d (%d, %d)", to_interval->reg_num(), to_interval->assigned_reg(), to_interval->assigned_regHi()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3938 assert(from_opr->is_constant(), "only for constants");
a61af66fc99e Initial load
duke
parents:
diff changeset
3939
a61af66fc99e Initial load
duke
parents:
diff changeset
3940 _mapping_from.append(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3941 _mapping_from_opr.append(from_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3942 _mapping_to.append(to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3943 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3944
a61af66fc99e Initial load
duke
parents:
diff changeset
3945 void MoveResolver::resolve_and_append_moves() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3946 if (has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3947 resolve_mappings();
a61af66fc99e Initial load
duke
parents:
diff changeset
3948 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3949 append_insertion_buffer();
a61af66fc99e Initial load
duke
parents:
diff changeset
3950 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3951
a61af66fc99e Initial load
duke
parents:
diff changeset
3952
a61af66fc99e Initial load
duke
parents:
diff changeset
3953
a61af66fc99e Initial load
duke
parents:
diff changeset
3954 // **** Implementation of Range *************************************
a61af66fc99e Initial load
duke
parents:
diff changeset
3955
a61af66fc99e Initial load
duke
parents:
diff changeset
3956 Range::Range(int from, int to, Range* next) :
a61af66fc99e Initial load
duke
parents:
diff changeset
3957 _from(from),
a61af66fc99e Initial load
duke
parents:
diff changeset
3958 _to(to),
a61af66fc99e Initial load
duke
parents:
diff changeset
3959 _next(next)
a61af66fc99e Initial load
duke
parents:
diff changeset
3960 {
a61af66fc99e Initial load
duke
parents:
diff changeset
3961 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3962
a61af66fc99e Initial load
duke
parents:
diff changeset
3963 // initialize sentinel
a61af66fc99e Initial load
duke
parents:
diff changeset
3964 Range* Range::_end = NULL;
1584
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
3965 void Range::initialize(Arena* arena) {
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
3966 _end = new (arena) Range(max_jint, max_jint, NULL);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3967 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3968
a61af66fc99e Initial load
duke
parents:
diff changeset
3969 int Range::intersects_at(Range* r2) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
3970 const Range* r1 = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
3971
a61af66fc99e Initial load
duke
parents:
diff changeset
3972 assert(r1 != NULL && r2 != NULL, "null ranges not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
3973 assert(r1 != _end && r2 != _end, "empty ranges not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
3974
a61af66fc99e Initial load
duke
parents:
diff changeset
3975 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
3976 if (r1->from() < r2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3977 if (r1->to() <= r2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3978 r1 = r1->next(); if (r1 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3979 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3980 return r2->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
3981 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3982 } else if (r2->from() < r1->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3983 if (r2->to() <= r1->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3984 r2 = r2->next(); if (r2 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3985 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3986 return r1->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
3987 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3988 } else { // r1->from() == r2->from()
a61af66fc99e Initial load
duke
parents:
diff changeset
3989 if (r1->from() == r1->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3990 r1 = r1->next(); if (r1 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3991 } else if (r2->from() == r2->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3992 r2 = r2->next(); if (r2 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3993 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3994 return r1->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
3995 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3996 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3997 } while (true);
a61af66fc99e Initial load
duke
parents:
diff changeset
3998 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3999
a61af66fc99e Initial load
duke
parents:
diff changeset
4000 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4001 void Range::print(outputStream* out) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4002 out->print("[%d, %d[ ", _from, _to);
a61af66fc99e Initial load
duke
parents:
diff changeset
4003 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4004 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4005
a61af66fc99e Initial load
duke
parents:
diff changeset
4006
a61af66fc99e Initial load
duke
parents:
diff changeset
4007
a61af66fc99e Initial load
duke
parents:
diff changeset
4008 // **** Implementation of Interval **********************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4009
a61af66fc99e Initial load
duke
parents:
diff changeset
4010 // initialize sentinel
a61af66fc99e Initial load
duke
parents:
diff changeset
4011 Interval* Interval::_end = NULL;
1584
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4012 void Interval::initialize(Arena* arena) {
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4013 Range::initialize(arena);
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4014 _end = new (arena) Interval(-1);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4015 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4016
a61af66fc99e Initial load
duke
parents:
diff changeset
4017 Interval::Interval(int reg_num) :
a61af66fc99e Initial load
duke
parents:
diff changeset
4018 _reg_num(reg_num),
a61af66fc99e Initial load
duke
parents:
diff changeset
4019 _type(T_ILLEGAL),
a61af66fc99e Initial load
duke
parents:
diff changeset
4020 _first(Range::end()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4021 _use_pos_and_kinds(12),
a61af66fc99e Initial load
duke
parents:
diff changeset
4022 _current(Range::end()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4023 _next(_end),
a61af66fc99e Initial load
duke
parents:
diff changeset
4024 _state(invalidState),
a61af66fc99e Initial load
duke
parents:
diff changeset
4025 _assigned_reg(LinearScan::any_reg),
a61af66fc99e Initial load
duke
parents:
diff changeset
4026 _assigned_regHi(LinearScan::any_reg),
a61af66fc99e Initial load
duke
parents:
diff changeset
4027 _cached_to(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
4028 _cached_opr(LIR_OprFact::illegalOpr),
a61af66fc99e Initial load
duke
parents:
diff changeset
4029 _cached_vm_reg(VMRegImpl::Bad()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4030 _split_children(0),
a61af66fc99e Initial load
duke
parents:
diff changeset
4031 _canonical_spill_slot(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
4032 _insert_move_when_activated(false),
a61af66fc99e Initial load
duke
parents:
diff changeset
4033 _register_hint(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
4034 _spill_state(noDefinitionFound),
a61af66fc99e Initial load
duke
parents:
diff changeset
4035 _spill_definition_pos(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
4036 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4037 _split_parent = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4038 _current_split_child = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4039 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4040
a61af66fc99e Initial load
duke
parents:
diff changeset
4041 int Interval::calc_to() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4042 assert(_first != Range::end(), "interval has no range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4043
a61af66fc99e Initial load
duke
parents:
diff changeset
4044 Range* r = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4045 while (r->next() != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4046 r = r->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4047 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4048 return r->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4049 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4050
a61af66fc99e Initial load
duke
parents:
diff changeset
4051
a61af66fc99e Initial load
duke
parents:
diff changeset
4052 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4053 // consistency check of split-children
a61af66fc99e Initial load
duke
parents:
diff changeset
4054 void Interval::check_split_children() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4055 if (_split_children.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4056 assert(is_split_parent(), "only split parents can have children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4057
a61af66fc99e Initial load
duke
parents:
diff changeset
4058 for (int i = 0; i < _split_children.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4059 Interval* i1 = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4060
a61af66fc99e Initial load
duke
parents:
diff changeset
4061 assert(i1->split_parent() == this, "not a split child of this interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4062 assert(i1->type() == type(), "must be equal for all split children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4063 assert(i1->canonical_spill_slot() == canonical_spill_slot(), "must be equal for all split children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4064
a61af66fc99e Initial load
duke
parents:
diff changeset
4065 for (int j = i + 1; j < _split_children.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4066 Interval* i2 = _split_children.at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
4067
a61af66fc99e Initial load
duke
parents:
diff changeset
4068 assert(i1->reg_num() != i2->reg_num(), "same register number");
a61af66fc99e Initial load
duke
parents:
diff changeset
4069
a61af66fc99e Initial load
duke
parents:
diff changeset
4070 if (i1->from() < i2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4071 assert(i1->to() <= i2->from() && i1->to() < i2->to(), "intervals overlapping");
a61af66fc99e Initial load
duke
parents:
diff changeset
4072 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4073 assert(i2->from() < i1->from(), "intervals start at same op_id");
a61af66fc99e Initial load
duke
parents:
diff changeset
4074 assert(i2->to() <= i1->from() && i2->to() < i1->to(), "intervals overlapping");
a61af66fc99e Initial load
duke
parents:
diff changeset
4075 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4076 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4077 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4078 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4079 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4080 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4081
a61af66fc99e Initial load
duke
parents:
diff changeset
4082 Interval* Interval::register_hint(bool search_split_child) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4083 if (!search_split_child) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4084 return _register_hint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4085 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4086
a61af66fc99e Initial load
duke
parents:
diff changeset
4087 if (_register_hint != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4088 assert(_register_hint->is_split_parent(), "ony split parents are valid hint registers");
a61af66fc99e Initial load
duke
parents:
diff changeset
4089
a61af66fc99e Initial load
duke
parents:
diff changeset
4090 if (_register_hint->assigned_reg() >= 0 && _register_hint->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4091 return _register_hint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4092
a61af66fc99e Initial load
duke
parents:
diff changeset
4093 } else if (_register_hint->_split_children.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4094 // search the first split child that has a register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
4095 int len = _register_hint->_split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4096 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4097 Interval* cur = _register_hint->_split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4098
a61af66fc99e Initial load
duke
parents:
diff changeset
4099 if (cur->assigned_reg() >= 0 && cur->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4100 return cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4103 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4104 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4105
a61af66fc99e Initial load
duke
parents:
diff changeset
4106 // no hint interval found that has a register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
4107 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4108 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4109
a61af66fc99e Initial load
duke
parents:
diff changeset
4110
a61af66fc99e Initial load
duke
parents:
diff changeset
4111 Interval* Interval::split_child_at_op_id(int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4112 assert(is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
4113 assert(op_id >= 0, "invalid op_id (method can not be called for spill moves)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4114
a61af66fc99e Initial load
duke
parents:
diff changeset
4115 Interval* result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4116 if (_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4117 result = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4118 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4119 result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4120 int len = _split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4121
a61af66fc99e Initial load
duke
parents:
diff changeset
4122 // in outputMode, the end of the interval (op_id == cur->to()) is not valid
a61af66fc99e Initial load
duke
parents:
diff changeset
4123 int to_offset = (mode == LIR_OpVisitState::outputMode ? 0 : 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4124
a61af66fc99e Initial load
duke
parents:
diff changeset
4125 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
4126 for (i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4127 Interval* cur = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4128 if (cur->from() <= op_id && op_id < cur->to() + to_offset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4129 if (i > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4130 // exchange current split child to start of list (faster access for next call)
a61af66fc99e Initial load
duke
parents:
diff changeset
4131 _split_children.at_put(i, _split_children.at(0));
a61af66fc99e Initial load
duke
parents:
diff changeset
4132 _split_children.at_put(0, cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4133 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4134
a61af66fc99e Initial load
duke
parents:
diff changeset
4135 // interval found
a61af66fc99e Initial load
duke
parents:
diff changeset
4136 result = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4137 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
4138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4140
a61af66fc99e Initial load
duke
parents:
diff changeset
4141 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4142 for (i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4143 Interval* tmp = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4144 if (tmp != result && tmp->from() <= op_id && op_id < tmp->to() + to_offset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4145 tty->print_cr("two valid result intervals found for op_id %d: %d and %d", op_id, result->reg_num(), tmp->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
4146 result->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4147 tmp->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4148 assert(false, "two valid result intervals found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4149 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4150 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4151 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4153
a61af66fc99e Initial load
duke
parents:
diff changeset
4154 assert(result != NULL, "no matching interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4155 assert(result->covers(op_id, mode), "op_id not covered by interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4156
a61af66fc99e Initial load
duke
parents:
diff changeset
4157 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4158 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4159
a61af66fc99e Initial load
duke
parents:
diff changeset
4160
a61af66fc99e Initial load
duke
parents:
diff changeset
4161 // returns the last split child that ends before the given op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
4162 Interval* Interval::split_child_before_op_id(int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4163 assert(op_id >= 0, "invalid op_id");
a61af66fc99e Initial load
duke
parents:
diff changeset
4164
a61af66fc99e Initial load
duke
parents:
diff changeset
4165 Interval* parent = split_parent();
a61af66fc99e Initial load
duke
parents:
diff changeset
4166 Interval* result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4167
a61af66fc99e Initial load
duke
parents:
diff changeset
4168 int len = parent->_split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4169 assert(len > 0, "no split children available");
a61af66fc99e Initial load
duke
parents:
diff changeset
4170
a61af66fc99e Initial load
duke
parents:
diff changeset
4171 for (int i = len - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4172 Interval* cur = parent->_split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4173 if (cur->to() <= op_id && (result == NULL || result->to() < cur->to())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4174 result = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4175 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4176 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4177
a61af66fc99e Initial load
duke
parents:
diff changeset
4178 assert(result != NULL, "no split child found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4179 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4180 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4181
a61af66fc99e Initial load
duke
parents:
diff changeset
4182
a61af66fc99e Initial load
duke
parents:
diff changeset
4183 // checks if op_id is covered by any split child
a61af66fc99e Initial load
duke
parents:
diff changeset
4184 bool Interval::split_child_covers(int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4185 assert(is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
4186 assert(op_id >= 0, "invalid op_id (method can not be called for spill moves)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4187
a61af66fc99e Initial load
duke
parents:
diff changeset
4188 if (_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4189 // simple case if interval was not split
a61af66fc99e Initial load
duke
parents:
diff changeset
4190 return covers(op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
4191
a61af66fc99e Initial load
duke
parents:
diff changeset
4192 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4193 // extended case: check all split children
a61af66fc99e Initial load
duke
parents:
diff changeset
4194 int len = _split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4195 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4196 Interval* cur = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4197 if (cur->covers(op_id, mode)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4198 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4199 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4201 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4204
a61af66fc99e Initial load
duke
parents:
diff changeset
4205
a61af66fc99e Initial load
duke
parents:
diff changeset
4206 // Note: use positions are sorted descending -> first use has highest index
a61af66fc99e Initial load
duke
parents:
diff changeset
4207 int Interval::first_usage(IntervalUseKind min_use_kind) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4208 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4209
a61af66fc99e Initial load
duke
parents:
diff changeset
4210 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4211 if (_use_pos_and_kinds.at(i + 1) >= min_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4212 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4213 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4214 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4215 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4217
a61af66fc99e Initial load
duke
parents:
diff changeset
4218 int Interval::next_usage(IntervalUseKind min_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4219 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4220
a61af66fc99e Initial load
duke
parents:
diff changeset
4221 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4222 if (_use_pos_and_kinds.at(i) >= from && _use_pos_and_kinds.at(i + 1) >= min_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4223 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4224 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4226 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4227 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4228
a61af66fc99e Initial load
duke
parents:
diff changeset
4229 int Interval::next_usage_exact(IntervalUseKind exact_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4230 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4231
a61af66fc99e Initial load
duke
parents:
diff changeset
4232 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4233 if (_use_pos_and_kinds.at(i) >= from && _use_pos_and_kinds.at(i + 1) == exact_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4234 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4235 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4237 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4238 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4239
a61af66fc99e Initial load
duke
parents:
diff changeset
4240 int Interval::previous_usage(IntervalUseKind min_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4241 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4242
a61af66fc99e Initial load
duke
parents:
diff changeset
4243 int prev = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4244 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4245 if (_use_pos_and_kinds.at(i) > from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4246 return prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4247 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4248 if (_use_pos_and_kinds.at(i + 1) >= min_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4249 prev = _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4252 return prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4253 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4254
a61af66fc99e Initial load
duke
parents:
diff changeset
4255 void Interval::add_use_pos(int pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4256 assert(covers(pos, LIR_OpVisitState::inputMode), "use position not covered by live range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4257
a61af66fc99e Initial load
duke
parents:
diff changeset
4258 // do not add use positions for precolored intervals because
a61af66fc99e Initial load
duke
parents:
diff changeset
4259 // they are never used
a61af66fc99e Initial load
duke
parents:
diff changeset
4260 if (use_kind != noUse && reg_num() >= LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4261 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4262 assert(_use_pos_and_kinds.length() % 2 == 0, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4263 for (int i = 0; i < _use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4264 assert(pos <= _use_pos_and_kinds.at(i), "already added a use-position with lower position");
a61af66fc99e Initial load
duke
parents:
diff changeset
4265 assert(_use_pos_and_kinds.at(i + 1) >= firstValidKind && _use_pos_and_kinds.at(i + 1) <= lastValidKind, "invalid use kind");
a61af66fc99e Initial load
duke
parents:
diff changeset
4266 if (i > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4267 assert(_use_pos_and_kinds.at(i) < _use_pos_and_kinds.at(i - 2), "not sorted descending");
a61af66fc99e Initial load
duke
parents:
diff changeset
4268 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4269 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4270 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4271
a61af66fc99e Initial load
duke
parents:
diff changeset
4272 // Note: add_use is called in descending order, so list gets sorted
a61af66fc99e Initial load
duke
parents:
diff changeset
4273 // automatically by just appending new use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4274 int len = _use_pos_and_kinds.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4275 if (len == 0 || _use_pos_and_kinds.at(len - 2) > pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4276 _use_pos_and_kinds.append(pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4277 _use_pos_and_kinds.append(use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4278 } else if (_use_pos_and_kinds.at(len - 1) < use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4279 assert(_use_pos_and_kinds.at(len - 2) == pos, "list not sorted correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
4280 _use_pos_and_kinds.at_put(len - 1, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4281 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4282 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4283 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4284
a61af66fc99e Initial load
duke
parents:
diff changeset
4285 void Interval::add_range(int from, int to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4286 assert(from < to, "invalid range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4287 assert(first() == Range::end() || to < first()->next()->from(), "not inserting at begin of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4288 assert(from <= first()->to(), "not inserting at begin of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4289
a61af66fc99e Initial load
duke
parents:
diff changeset
4290 if (first()->from() <= to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4291 // join intersecting ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4292 first()->set_from(MIN2(from, first()->from()));
a61af66fc99e Initial load
duke
parents:
diff changeset
4293 first()->set_to (MAX2(to, first()->to()));
a61af66fc99e Initial load
duke
parents:
diff changeset
4294 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4295 // insert new range
a61af66fc99e Initial load
duke
parents:
diff changeset
4296 _first = new Range(from, to, first());
a61af66fc99e Initial load
duke
parents:
diff changeset
4297 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4298 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4299
a61af66fc99e Initial load
duke
parents:
diff changeset
4300 Interval* Interval::new_split_child() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4301 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4302 Interval* result = new Interval(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4303 result->set_type(type());
a61af66fc99e Initial load
duke
parents:
diff changeset
4304
a61af66fc99e Initial load
duke
parents:
diff changeset
4305 Interval* parent = split_parent();
a61af66fc99e Initial load
duke
parents:
diff changeset
4306 result->_split_parent = parent;
a61af66fc99e Initial load
duke
parents:
diff changeset
4307 result->set_register_hint(parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
4308
a61af66fc99e Initial load
duke
parents:
diff changeset
4309 // insert new interval in children-list of parent
a61af66fc99e Initial load
duke
parents:
diff changeset
4310 if (parent->_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4311 assert(is_split_parent(), "list must be initialized at first split");
a61af66fc99e Initial load
duke
parents:
diff changeset
4312
a61af66fc99e Initial load
duke
parents:
diff changeset
4313 parent->_split_children = IntervalList(4);
a61af66fc99e Initial load
duke
parents:
diff changeset
4314 parent->_split_children.append(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
4315 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4316 parent->_split_children.append(result);
a61af66fc99e Initial load
duke
parents:
diff changeset
4317
a61af66fc99e Initial load
duke
parents:
diff changeset
4318 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4319 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4320
a61af66fc99e Initial load
duke
parents:
diff changeset
4321 // split this interval at the specified position and return
a61af66fc99e Initial load
duke
parents:
diff changeset
4322 // the remainder as a new interval.
a61af66fc99e Initial load
duke
parents:
diff changeset
4323 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4324 // when an interval is split, a bi-directional link is established between the original interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4325 // (the split parent) and the intervals that are split off this interval (the split children)
a61af66fc99e Initial load
duke
parents:
diff changeset
4326 // When a split child is split again, the new created interval is also a direct child
a61af66fc99e Initial load
duke
parents:
diff changeset
4327 // of the original parent (there is no tree of split children stored, but a flat list)
a61af66fc99e Initial load
duke
parents:
diff changeset
4328 // All split children are spilled to the same stack slot (stored in _canonical_spill_slot)
a61af66fc99e Initial load
duke
parents:
diff changeset
4329 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4330 // Note: The new interval has no valid reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
4331 Interval* Interval::split(int split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4332 assert(LinearScan::is_virtual_interval(this), "cannot split fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4333
a61af66fc99e Initial load
duke
parents:
diff changeset
4334 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4335 Interval* result = new_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
4336
a61af66fc99e Initial load
duke
parents:
diff changeset
4337 // split the ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4338 Range* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4339 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4340 while (cur != Range::end() && cur->to() <= split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4341 prev = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4342 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4343 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4344 assert(cur != Range::end(), "split interval after end of last range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4345
a61af66fc99e Initial load
duke
parents:
diff changeset
4346 if (cur->from() < split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4347 result->_first = new Range(split_pos, cur->to(), cur->next());
a61af66fc99e Initial load
duke
parents:
diff changeset
4348 cur->set_to(split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4349 cur->set_next(Range::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4350
a61af66fc99e Initial load
duke
parents:
diff changeset
4351 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4352 assert(prev != NULL, "split before start of first range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4353 result->_first = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4354 prev->set_next(Range::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4355 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4356 result->_current = result->_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4357 _cached_to = -1; // clear cached value
a61af66fc99e Initial load
duke
parents:
diff changeset
4358
a61af66fc99e Initial load
duke
parents:
diff changeset
4359 // split list of use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4360 int total_len = _use_pos_and_kinds.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4361 int start_idx = total_len - 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4362 while (start_idx >= 0 && _use_pos_and_kinds.at(start_idx) < split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4363 start_idx -= 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4364 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4365
a61af66fc99e Initial load
duke
parents:
diff changeset
4366 intStack new_use_pos_and_kinds(total_len - start_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
4367 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
4368 for (i = start_idx + 2; i < total_len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4369 new_use_pos_and_kinds.append(_use_pos_and_kinds.at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
4370 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4371
a61af66fc99e Initial load
duke
parents:
diff changeset
4372 _use_pos_and_kinds.truncate(start_idx + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
4373 result->_use_pos_and_kinds = _use_pos_and_kinds;
a61af66fc99e Initial load
duke
parents:
diff changeset
4374 _use_pos_and_kinds = new_use_pos_and_kinds;
a61af66fc99e Initial load
duke
parents:
diff changeset
4375
a61af66fc99e Initial load
duke
parents:
diff changeset
4376 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4377 assert(_use_pos_and_kinds.length() % 2 == 0, "must have use kind for each use pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
4378 assert(result->_use_pos_and_kinds.length() % 2 == 0, "must have use kind for each use pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
4379 assert(_use_pos_and_kinds.length() + result->_use_pos_and_kinds.length() == total_len, "missed some entries");
a61af66fc99e Initial load
duke
parents:
diff changeset
4380
a61af66fc99e Initial load
duke
parents:
diff changeset
4381 for (i = 0; i < _use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4382 assert(_use_pos_and_kinds.at(i) < split_pos, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4383 assert(_use_pos_and_kinds.at(i + 1) >= firstValidKind && _use_pos_and_kinds.at(i + 1) <= lastValidKind, "invalid use kind");
a61af66fc99e Initial load
duke
parents:
diff changeset
4384 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4385 for (i = 0; i < result->_use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4386 assert(result->_use_pos_and_kinds.at(i) >= split_pos, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4387 assert(result->_use_pos_and_kinds.at(i + 1) >= firstValidKind && result->_use_pos_and_kinds.at(i + 1) <= lastValidKind, "invalid use kind");
a61af66fc99e Initial load
duke
parents:
diff changeset
4388 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4389 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4390
a61af66fc99e Initial load
duke
parents:
diff changeset
4391 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4392 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4393
a61af66fc99e Initial load
duke
parents:
diff changeset
4394 // split this interval at the specified position and return
a61af66fc99e Initial load
duke
parents:
diff changeset
4395 // the head as a new interval (the original interval is the tail)
a61af66fc99e Initial load
duke
parents:
diff changeset
4396 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4397 // Currently, only the first range can be split, and the new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4398 // must not have split positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4399 Interval* Interval::split_from_start(int split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4400 assert(LinearScan::is_virtual_interval(this), "cannot split fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4401 assert(split_pos > from() && split_pos < to(), "can only split inside interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4402 assert(split_pos > _first->from() && split_pos <= _first->to(), "can only split inside first range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4403 assert(first_usage(noUse) > split_pos, "can not split when use positions are present");
a61af66fc99e Initial load
duke
parents:
diff changeset
4404
a61af66fc99e Initial load
duke
parents:
diff changeset
4405 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4406 Interval* result = new_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
4407
a61af66fc99e Initial load
duke
parents:
diff changeset
4408 // the new created interval has only one range (checked by assertion above),
a61af66fc99e Initial load
duke
parents:
diff changeset
4409 // so the splitting of the ranges is very simple
a61af66fc99e Initial load
duke
parents:
diff changeset
4410 result->add_range(_first->from(), split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4411
a61af66fc99e Initial load
duke
parents:
diff changeset
4412 if (split_pos == _first->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4413 assert(_first->next() != Range::end(), "must not be at end");
a61af66fc99e Initial load
duke
parents:
diff changeset
4414 _first = _first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4415 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4416 _first->set_from(split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4417 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4418
a61af66fc99e Initial load
duke
parents:
diff changeset
4419 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4420 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4421
a61af66fc99e Initial load
duke
parents:
diff changeset
4422
a61af66fc99e Initial load
duke
parents:
diff changeset
4423 // returns true if the op_id is inside the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4424 bool Interval::covers(int op_id, LIR_OpVisitState::OprMode mode) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4425 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4426
a61af66fc99e Initial load
duke
parents:
diff changeset
4427 while (cur != Range::end() && cur->to() < op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4428 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4430 if (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4431 assert(cur->to() != cur->next()->from(), "ranges not separated");
a61af66fc99e Initial load
duke
parents:
diff changeset
4432
a61af66fc99e Initial load
duke
parents:
diff changeset
4433 if (mode == LIR_OpVisitState::outputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4434 return cur->from() <= op_id && op_id < cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4435 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4436 return cur->from() <= op_id && op_id <= cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4437 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4438 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4439 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4440 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4441
a61af66fc99e Initial load
duke
parents:
diff changeset
4442 // returns true if the interval has any hole between hole_from and hole_to
a61af66fc99e Initial load
duke
parents:
diff changeset
4443 // (even if the hole has only the length 1)
a61af66fc99e Initial load
duke
parents:
diff changeset
4444 bool Interval::has_hole_between(int hole_from, int hole_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4445 assert(hole_from < hole_to, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4446 assert(from() <= hole_from && hole_to <= to(), "index out of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4447
a61af66fc99e Initial load
duke
parents:
diff changeset
4448 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4449 while (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4450 assert(cur->to() < cur->next()->from(), "no space between ranges");
a61af66fc99e Initial load
duke
parents:
diff changeset
4451
a61af66fc99e Initial load
duke
parents:
diff changeset
4452 // hole-range starts before this range -> hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4453 if (hole_from < cur->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4454 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4455
a61af66fc99e Initial load
duke
parents:
diff changeset
4456 // hole-range completely inside this range -> no hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4457 } else if (hole_to <= cur->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4458 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4459
a61af66fc99e Initial load
duke
parents:
diff changeset
4460 // overlapping of hole-range with this range -> hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4461 } else if (hole_from <= cur->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4462 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4463 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4464
a61af66fc99e Initial load
duke
parents:
diff changeset
4465 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4466 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4467
a61af66fc99e Initial load
duke
parents:
diff changeset
4468 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4469 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4470
a61af66fc99e Initial load
duke
parents:
diff changeset
4471
a61af66fc99e Initial load
duke
parents:
diff changeset
4472 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4473 void Interval::print(outputStream* out) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4474 const char* SpillState2Name[] = { "no definition", "no spill store", "one spill store", "store at definition", "start in memory", "no optimization" };
a61af66fc99e Initial load
duke
parents:
diff changeset
4475 const char* UseKind2Name[] = { "N", "L", "S", "M" };
a61af66fc99e Initial load
duke
parents:
diff changeset
4476
a61af66fc99e Initial load
duke
parents:
diff changeset
4477 const char* type_name;
a61af66fc99e Initial load
duke
parents:
diff changeset
4478 LIR_Opr opr = LIR_OprFact::illegal();
a61af66fc99e Initial load
duke
parents:
diff changeset
4479 if (reg_num() < LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4480 type_name = "fixed";
a61af66fc99e Initial load
duke
parents:
diff changeset
4481 // need a temporary operand for fixed intervals because type() cannot be called
a61af66fc99e Initial load
duke
parents:
diff changeset
4482 if (assigned_reg() >= pd_first_cpu_reg && assigned_reg() <= pd_last_cpu_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4483 opr = LIR_OprFact::single_cpu(assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
4484 } else if (assigned_reg() >= pd_first_fpu_reg && assigned_reg() <= pd_last_fpu_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4485 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
4486 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4487 } else if (assigned_reg() >= pd_first_xmm_reg && assigned_reg() <= pd_last_xmm_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4488 opr = LIR_OprFact::single_xmm(assigned_reg() - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
4489 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4490 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4491 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
4492 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4493 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4494 type_name = type2name(type());
a61af66fc99e Initial load
duke
parents:
diff changeset
4495 if (assigned_reg() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4496 opr = LinearScan::calc_operand_for_interval(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
4497 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4499
a61af66fc99e Initial load
duke
parents:
diff changeset
4500 out->print("%d %s ", reg_num(), type_name);
a61af66fc99e Initial load
duke
parents:
diff changeset
4501 if (opr->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4502 out->print("\"");
a61af66fc99e Initial load
duke
parents:
diff changeset
4503 opr->print(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
4504 out->print("\" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
4505 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4506 out->print("%d %d ", split_parent()->reg_num(), (register_hint(false) != NULL ? register_hint(false)->reg_num() : -1));
a61af66fc99e Initial load
duke
parents:
diff changeset
4507
a61af66fc99e Initial load
duke
parents:
diff changeset
4508 // print ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4509 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4510 while (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4511 cur->print(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
4512 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4513 assert(cur != NULL, "range list not closed with range sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
4514 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4515
a61af66fc99e Initial load
duke
parents:
diff changeset
4516 // print use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4517 int prev = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4518 assert(_use_pos_and_kinds.length() % 2 == 0, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4519 for (int i =_use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4520 assert(_use_pos_and_kinds.at(i + 1) >= firstValidKind && _use_pos_and_kinds.at(i + 1) <= lastValidKind, "invalid use kind");
a61af66fc99e Initial load
duke
parents:
diff changeset
4521 assert(prev < _use_pos_and_kinds.at(i), "use positions not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
4522
a61af66fc99e Initial load
duke
parents:
diff changeset
4523 out->print("%d %s ", _use_pos_and_kinds.at(i), UseKind2Name[_use_pos_and_kinds.at(i + 1)]);
a61af66fc99e Initial load
duke
parents:
diff changeset
4524 prev = _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4525 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4526
a61af66fc99e Initial load
duke
parents:
diff changeset
4527 out->print(" \"%s\"", SpillState2Name[spill_state()]);
a61af66fc99e Initial load
duke
parents:
diff changeset
4528 out->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4529 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4530 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4531
a61af66fc99e Initial load
duke
parents:
diff changeset
4532
a61af66fc99e Initial load
duke
parents:
diff changeset
4533
a61af66fc99e Initial load
duke
parents:
diff changeset
4534 // **** Implementation of IntervalWalker ****************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4535
a61af66fc99e Initial load
duke
parents:
diff changeset
4536 IntervalWalker::IntervalWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4537 : _compilation(allocator->compilation())
a61af66fc99e Initial load
duke
parents:
diff changeset
4538 , _allocator(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
4539 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4540 _unhandled_first[fixedKind] = unhandled_fixed_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4541 _unhandled_first[anyKind] = unhandled_any_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4542 _active_first[fixedKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4543 _inactive_first[fixedKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4544 _active_first[anyKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4545 _inactive_first[anyKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4546 _current_position = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4547 _current = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4548 next_interval();
a61af66fc99e Initial load
duke
parents:
diff changeset
4549 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4550
a61af66fc99e Initial load
duke
parents:
diff changeset
4551
a61af66fc99e Initial load
duke
parents:
diff changeset
4552 // append interval at top of list
a61af66fc99e Initial load
duke
parents:
diff changeset
4553 void IntervalWalker::append_unsorted(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4554 interval->set_next(*list); *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4555 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4556
a61af66fc99e Initial load
duke
parents:
diff changeset
4557
a61af66fc99e Initial load
duke
parents:
diff changeset
4558 // append interval in order of current range from()
a61af66fc99e Initial load
duke
parents:
diff changeset
4559 void IntervalWalker::append_sorted(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4560 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4561 Interval* cur = *list;
a61af66fc99e Initial load
duke
parents:
diff changeset
4562 while (cur->current_from() < interval->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4563 prev = cur; cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4564 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4565 if (prev == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4566 *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4567 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4568 prev->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
4569 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4570 interval->set_next(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4571 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4572
a61af66fc99e Initial load
duke
parents:
diff changeset
4573 void IntervalWalker::append_to_unhandled(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4574 assert(interval->from() >= current()->current_from(), "cannot append new interval before current walk position");
a61af66fc99e Initial load
duke
parents:
diff changeset
4575
a61af66fc99e Initial load
duke
parents:
diff changeset
4576 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4577 Interval* cur = *list;
a61af66fc99e Initial load
duke
parents:
diff changeset
4578 while (cur->from() < interval->from() || (cur->from() == interval->from() && cur->first_usage(noUse) < interval->first_usage(noUse))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4579 prev = cur; cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4580 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4581 if (prev == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4582 *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4583 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4584 prev->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
4585 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4586 interval->set_next(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4587 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4588
a61af66fc99e Initial load
duke
parents:
diff changeset
4589
a61af66fc99e Initial load
duke
parents:
diff changeset
4590 inline bool IntervalWalker::remove_from_list(Interval** list, Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4591 while (*list != Interval::end() && *list != i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4592 list = (*list)->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4593 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4594 if (*list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4595 assert(*list == i, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4596 *list = (*list)->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4597 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4598 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4599 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4600 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4601 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4602
a61af66fc99e Initial load
duke
parents:
diff changeset
4603 void IntervalWalker::remove_from_list(Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4604 bool deleted;
a61af66fc99e Initial load
duke
parents:
diff changeset
4605
a61af66fc99e Initial load
duke
parents:
diff changeset
4606 if (i->state() == activeState) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4607 deleted = remove_from_list(active_first_addr(anyKind), i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4608 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4609 assert(i->state() == inactiveState, "invalid state");
a61af66fc99e Initial load
duke
parents:
diff changeset
4610 deleted = remove_from_list(inactive_first_addr(anyKind), i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4611 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4612
a61af66fc99e Initial load
duke
parents:
diff changeset
4613 assert(deleted, "interval has not been found in list");
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 void IntervalWalker::walk_to(IntervalState state, int from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4618 assert (state == activeState || state == inactiveState, "wrong state");
a61af66fc99e Initial load
duke
parents:
diff changeset
4619 for_each_interval_kind(kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4620 Interval** prev = state == activeState ? active_first_addr(kind) : inactive_first_addr(kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4621 Interval* next = *prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4622 while (next->current_from() <= from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4623 Interval* cur = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
4624 next = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4625
a61af66fc99e Initial load
duke
parents:
diff changeset
4626 bool range_has_changed = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4627 while (cur->current_to() <= from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4628 cur->next_range();
a61af66fc99e Initial load
duke
parents:
diff changeset
4629 range_has_changed = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4630 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4631
a61af66fc99e Initial load
duke
parents:
diff changeset
4632 // also handle move from inactive list to active list
a61af66fc99e Initial load
duke
parents:
diff changeset
4633 range_has_changed = range_has_changed || (state == inactiveState && cur->current_from() <= from);
a61af66fc99e Initial load
duke
parents:
diff changeset
4634
a61af66fc99e Initial load
duke
parents:
diff changeset
4635 if (range_has_changed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4636 // remove cur from list
a61af66fc99e Initial load
duke
parents:
diff changeset
4637 *prev = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
4638 if (cur->current_at_end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4639 // move to handled state (not maintained as a list)
a61af66fc99e Initial load
duke
parents:
diff changeset
4640 cur->set_state(handledState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4641 interval_moved(cur, kind, state, handledState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4642 } else if (cur->current_from() <= from){
a61af66fc99e Initial load
duke
parents:
diff changeset
4643 // sort into active list
a61af66fc99e Initial load
duke
parents:
diff changeset
4644 append_sorted(active_first_addr(kind), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4645 cur->set_state(activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4646 if (*prev == cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4647 assert(state == activeState, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4648 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4649 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4650 interval_moved(cur, kind, state, activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4651 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4652 // sort into inactive list
a61af66fc99e Initial load
duke
parents:
diff changeset
4653 append_sorted(inactive_first_addr(kind), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4654 cur->set_state(inactiveState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4655 if (*prev == cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4656 assert(state == inactiveState, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4657 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4658 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4659 interval_moved(cur, kind, state, inactiveState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4660 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4661 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4662 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4663 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
4664 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4665 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4666 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4667 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4668
a61af66fc99e Initial load
duke
parents:
diff changeset
4669
a61af66fc99e Initial load
duke
parents:
diff changeset
4670 void IntervalWalker::next_interval() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4671 IntervalKind kind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4672 Interval* any = _unhandled_first[anyKind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4673 Interval* fixed = _unhandled_first[fixedKind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4674
a61af66fc99e Initial load
duke
parents:
diff changeset
4675 if (any != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4676 // intervals may start at same position -> prefer fixed interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4677 kind = fixed != Interval::end() && fixed->from() <= any->from() ? fixedKind : anyKind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4678
a61af66fc99e Initial load
duke
parents:
diff changeset
4679 assert (kind == fixedKind && fixed->from() <= any->from() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
4680 kind == anyKind && any->from() <= fixed->from(), "wrong interval!!!");
a61af66fc99e Initial load
duke
parents:
diff changeset
4681 assert(any == Interval::end() || fixed == Interval::end() || any->from() != fixed->from() || kind == fixedKind, "if fixed and any-Interval start at same position, fixed must be processed first");
a61af66fc99e Initial load
duke
parents:
diff changeset
4682
a61af66fc99e Initial load
duke
parents:
diff changeset
4683 } else if (fixed != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4684 kind = fixedKind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4685 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4686 _current = NULL; return;
a61af66fc99e Initial load
duke
parents:
diff changeset
4687 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4688 _current_kind = kind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4689 _current = _unhandled_first[kind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4690 _unhandled_first[kind] = _current->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4691 _current->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4692 _current->rewind_range();
a61af66fc99e Initial load
duke
parents:
diff changeset
4693 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4694
a61af66fc99e Initial load
duke
parents:
diff changeset
4695
a61af66fc99e Initial load
duke
parents:
diff changeset
4696 void IntervalWalker::walk_to(int lir_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4697 assert(_current_position <= lir_op_id, "can not walk backwards");
a61af66fc99e Initial load
duke
parents:
diff changeset
4698 while (current() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4699 bool is_active = current()->from() <= lir_op_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4700 int id = is_active ? current()->from() : lir_op_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4701
a61af66fc99e Initial load
duke
parents:
diff changeset
4702 TRACE_LINEAR_SCAN(2, if (_current_position < id) { tty->cr(); tty->print_cr("walk_to(%d) **************************************************************", id); })
a61af66fc99e Initial load
duke
parents:
diff changeset
4703
a61af66fc99e Initial load
duke
parents:
diff changeset
4704 // set _current_position prior to call of walk_to
a61af66fc99e Initial load
duke
parents:
diff changeset
4705 _current_position = id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4706
a61af66fc99e Initial load
duke
parents:
diff changeset
4707 // call walk_to even if _current_position == id
a61af66fc99e Initial load
duke
parents:
diff changeset
4708 walk_to(activeState, id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4709 walk_to(inactiveState, id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4710
a61af66fc99e Initial load
duke
parents:
diff changeset
4711 if (is_active) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4712 current()->set_state(activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4713 if (activate_current()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4714 append_sorted(active_first_addr(current_kind()), current());
a61af66fc99e Initial load
duke
parents:
diff changeset
4715 interval_moved(current(), current_kind(), unhandledState, activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4716 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4717
a61af66fc99e Initial load
duke
parents:
diff changeset
4718 next_interval();
a61af66fc99e Initial load
duke
parents:
diff changeset
4719 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4720 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
4721 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4722 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4723 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4724
a61af66fc99e Initial load
duke
parents:
diff changeset
4725 void IntervalWalker::interval_moved(Interval* interval, IntervalKind kind, IntervalState from, IntervalState to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4726 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4727 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4728 #define print_state(state) \
a61af66fc99e Initial load
duke
parents:
diff changeset
4729 switch(state) {\
a61af66fc99e Initial load
duke
parents:
diff changeset
4730 case unhandledState: tty->print("unhandled"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4731 case activeState: tty->print("active"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4732 case inactiveState: tty->print("inactive"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4733 case handledState: tty->print("handled"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4734 default: ShouldNotReachHere(); \
a61af66fc99e Initial load
duke
parents:
diff changeset
4735 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4736
a61af66fc99e Initial load
duke
parents:
diff changeset
4737 print_state(from); tty->print(" to "); print_state(to);
a61af66fc99e Initial load
duke
parents:
diff changeset
4738 tty->fill_to(23);
a61af66fc99e Initial load
duke
parents:
diff changeset
4739 interval->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4740
a61af66fc99e Initial load
duke
parents:
diff changeset
4741 #undef print_state
a61af66fc99e Initial load
duke
parents:
diff changeset
4742 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4743 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4744 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4745
a61af66fc99e Initial load
duke
parents:
diff changeset
4746
a61af66fc99e Initial load
duke
parents:
diff changeset
4747
a61af66fc99e Initial load
duke
parents:
diff changeset
4748 // **** Implementation of LinearScanWalker **************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4749
a61af66fc99e Initial load
duke
parents:
diff changeset
4750 LinearScanWalker::LinearScanWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4751 : IntervalWalker(allocator, unhandled_fixed_first, unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4752 , _move_resolver(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
4753 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4754 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4755 _spill_intervals[i] = new IntervalList(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
4756 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4757 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4758
a61af66fc99e Initial load
duke
parents:
diff changeset
4759
a61af66fc99e Initial load
duke
parents:
diff changeset
4760 inline void LinearScanWalker::init_use_lists(bool only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4761 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4762 _use_pos[i] = max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4763
a61af66fc99e Initial load
duke
parents:
diff changeset
4764 if (!only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4765 _block_pos[i] = max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4766 _spill_intervals[i]->clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
4767 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4768 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4769 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4770
a61af66fc99e Initial load
duke
parents:
diff changeset
4771 inline void LinearScanWalker::exclude_from_use(int reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4772 assert(reg < LinearScan::nof_regs, "interval must have a register assigned (stack slots not allowed)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4773 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4774 _use_pos[reg] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4775 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4776 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4777 inline void LinearScanWalker::exclude_from_use(Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4778 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4779
a61af66fc99e Initial load
duke
parents:
diff changeset
4780 exclude_from_use(i->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
4781 exclude_from_use(i->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
4782 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4783
a61af66fc99e Initial load
duke
parents:
diff changeset
4784 inline void LinearScanWalker::set_use_pos(int reg, Interval* i, int use_pos, bool only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4785 assert(use_pos != 0, "must use exclude_from_use to set use_pos to 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
4786
a61af66fc99e Initial load
duke
parents:
diff changeset
4787 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4788 if (_use_pos[reg] > use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4789 _use_pos[reg] = use_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4790 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4791 if (!only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4792 _spill_intervals[reg]->append(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4793 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4794 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4795 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4796 inline void LinearScanWalker::set_use_pos(Interval* i, int use_pos, bool only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4797 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4798 if (use_pos != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4799 set_use_pos(i->assigned_reg(), i, use_pos, only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4800 set_use_pos(i->assigned_regHi(), i, use_pos, only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4801 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4802 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4803
a61af66fc99e Initial load
duke
parents:
diff changeset
4804 inline void LinearScanWalker::set_block_pos(int reg, Interval* i, int block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4805 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4806 if (_block_pos[reg] > block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4807 _block_pos[reg] = block_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4808 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4809 if (_use_pos[reg] > block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4810 _use_pos[reg] = block_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4811 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4812 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4813 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4814 inline void LinearScanWalker::set_block_pos(Interval* i, int block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4815 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4816 if (block_pos != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4817 set_block_pos(i->assigned_reg(), i, block_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4818 set_block_pos(i->assigned_regHi(), i, block_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4819 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4820 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4821
a61af66fc99e Initial load
duke
parents:
diff changeset
4822
a61af66fc99e Initial load
duke
parents:
diff changeset
4823 void LinearScanWalker::free_exclude_active_fixed() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4824 Interval* list = active_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4825 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4826 assert(list->assigned_reg() < LinearScan::nof_regs, "active interval must have a register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4827 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4828 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4829 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4830 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4831
a61af66fc99e Initial load
duke
parents:
diff changeset
4832 void LinearScanWalker::free_exclude_active_any() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4833 Interval* list = active_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4834 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4835 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4836 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4837 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4838 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4839
a61af66fc99e Initial load
duke
parents:
diff changeset
4840 void LinearScanWalker::free_collect_inactive_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4841 Interval* list = inactive_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4842 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4843 if (cur->to() <= list->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4844 assert(list->current_intersects_at(cur) == -1, "must not intersect");
a61af66fc99e Initial load
duke
parents:
diff changeset
4845 set_use_pos(list, list->current_from(), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4846 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4847 set_use_pos(list, list->current_intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4848 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4849 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4850 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4851 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4852
a61af66fc99e Initial load
duke
parents:
diff changeset
4853 void LinearScanWalker::free_collect_inactive_any(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4854 Interval* list = inactive_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4855 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4856 set_use_pos(list, list->current_intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4857 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4858 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4859 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4860
a61af66fc99e Initial load
duke
parents:
diff changeset
4861 void LinearScanWalker::free_collect_unhandled(IntervalKind kind, Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4862 Interval* list = unhandled_first(kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4863 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4864 set_use_pos(list, list->intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4865 if (kind == fixedKind && cur->to() <= list->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4866 set_use_pos(list, list->from(), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4867 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4868 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4869 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4870 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4871
a61af66fc99e Initial load
duke
parents:
diff changeset
4872 void LinearScanWalker::spill_exclude_active_fixed() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4873 Interval* list = active_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4874 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4875 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4876 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4877 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4878 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4879
a61af66fc99e Initial load
duke
parents:
diff changeset
4880 void LinearScanWalker::spill_block_unhandled_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4881 Interval* list = unhandled_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4882 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4883 set_block_pos(list, list->intersects_at(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
4884 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4885 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4886 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4887
a61af66fc99e Initial load
duke
parents:
diff changeset
4888 void LinearScanWalker::spill_block_inactive_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4889 Interval* list = inactive_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4890 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4891 if (cur->to() > list->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4892 set_block_pos(list, list->current_intersects_at(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
4893 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4894 assert(list->current_intersects_at(cur) == -1, "invalid optimization: intervals intersect");
a61af66fc99e Initial load
duke
parents:
diff changeset
4895 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4896
a61af66fc99e Initial load
duke
parents:
diff changeset
4897 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4898 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4899 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4900
a61af66fc99e Initial load
duke
parents:
diff changeset
4901 void LinearScanWalker::spill_collect_active_any() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4902 Interval* list = active_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4903 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4904 set_use_pos(list, MIN2(list->next_usage(loopEndMarker, _current_position), list->to()), false);
a61af66fc99e Initial load
duke
parents:
diff changeset
4905 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4906 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4907 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4908
a61af66fc99e Initial load
duke
parents:
diff changeset
4909 void LinearScanWalker::spill_collect_inactive_any(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4910 Interval* list = inactive_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4911 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4912 if (list->current_intersects(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4913 set_use_pos(list, MIN2(list->next_usage(loopEndMarker, _current_position), list->to()), false);
a61af66fc99e Initial load
duke
parents:
diff changeset
4914 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4915 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4916 }
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::insert_move(int op_id, Interval* src_it, Interval* dst_it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4921 // output all moves here. When source and target are equal, the move is
a61af66fc99e Initial load
duke
parents:
diff changeset
4922 // optimized away later in assign_reg_nums
a61af66fc99e Initial load
duke
parents:
diff changeset
4923
a61af66fc99e Initial load
duke
parents:
diff changeset
4924 op_id = (op_id + 1) & ~1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4925 BlockBegin* op_block = allocator()->block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4926 assert(op_id > 0 && allocator()->block_of_op_with_id(op_id - 2) == op_block, "cannot insert move at block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
4927
a61af66fc99e Initial load
duke
parents:
diff changeset
4928 // calculate index of instruction inside instruction list of current block
a61af66fc99e Initial load
duke
parents:
diff changeset
4929 // the minimal index (for a block with no spill moves) can be calculated because the
a61af66fc99e Initial load
duke
parents:
diff changeset
4930 // numbering of instructions is known.
a61af66fc99e Initial load
duke
parents:
diff changeset
4931 // When the block already contains spill moves, the index must be increased until the
a61af66fc99e Initial load
duke
parents:
diff changeset
4932 // correct index is reached.
a61af66fc99e Initial load
duke
parents:
diff changeset
4933 LIR_OpList* list = op_block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
4934 int index = (op_id - list->at(0)->id()) / 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4935 assert(list->at(index)->id() <= op_id, "error in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
4936
a61af66fc99e Initial load
duke
parents:
diff changeset
4937 while (list->at(index)->id() != op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4938 index++;
a61af66fc99e Initial load
duke
parents:
diff changeset
4939 assert(0 <= index && index < list->length(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
4940 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4941 assert(1 <= index && index < list->length(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
4942 assert(list->at(index)->id() == op_id, "error in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
4943
a61af66fc99e Initial load
duke
parents:
diff changeset
4944 // insert new instruction before instruction at position index
a61af66fc99e Initial load
duke
parents:
diff changeset
4945 _move_resolver.move_insert_position(op_block->lir(), index - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4946 _move_resolver.add_mapping(src_it, dst_it);
a61af66fc99e Initial load
duke
parents:
diff changeset
4947 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4948
a61af66fc99e Initial load
duke
parents:
diff changeset
4949
a61af66fc99e Initial load
duke
parents:
diff changeset
4950 int LinearScanWalker::find_optimal_split_pos(BlockBegin* min_block, BlockBegin* max_block, int max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4951 int from_block_nr = min_block->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
4952 int to_block_nr = max_block->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
4953
a61af66fc99e Initial load
duke
parents:
diff changeset
4954 assert(0 <= from_block_nr && from_block_nr < block_count(), "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4955 assert(0 <= to_block_nr && to_block_nr < block_count(), "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4956 assert(from_block_nr < to_block_nr, "must cross block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
4957
a61af66fc99e Initial load
duke
parents:
diff changeset
4958 // Try to split at end of max_block. If this would be after
a61af66fc99e Initial load
duke
parents:
diff changeset
4959 // max_split_pos, then use the begin of max_block
a61af66fc99e Initial load
duke
parents:
diff changeset
4960 int optimal_split_pos = max_block->last_lir_instruction_id() + 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4961 if (optimal_split_pos > max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4962 optimal_split_pos = max_block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
4963 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4964
a61af66fc99e Initial load
duke
parents:
diff changeset
4965 int min_loop_depth = max_block->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
4966 for (int i = to_block_nr - 1; i >= from_block_nr; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4967 BlockBegin* cur = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4968
a61af66fc99e Initial load
duke
parents:
diff changeset
4969 if (cur->loop_depth() < min_loop_depth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4970 // block with lower loop-depth found -> split at the end of this block
a61af66fc99e Initial load
duke
parents:
diff changeset
4971 min_loop_depth = cur->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
4972 optimal_split_pos = cur->last_lir_instruction_id() + 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4973 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4974 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4975 assert(optimal_split_pos > allocator()->max_lir_op_id() || allocator()->is_block_begin(optimal_split_pos), "algorithm must move split pos to block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
4976
a61af66fc99e Initial load
duke
parents:
diff changeset
4977 return optimal_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4978 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4979
a61af66fc99e Initial load
duke
parents:
diff changeset
4980
a61af66fc99e Initial load
duke
parents:
diff changeset
4981 int LinearScanWalker::find_optimal_split_pos(Interval* it, int min_split_pos, int max_split_pos, bool do_loop_optimization) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4982 int optimal_split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4983 if (min_split_pos == max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4984 // trivial case, no optimization of split position possible
a61af66fc99e Initial load
duke
parents:
diff changeset
4985 TRACE_LINEAR_SCAN(4, tty->print_cr(" min-pos and max-pos are equal, no optimization possible"));
a61af66fc99e Initial load
duke
parents:
diff changeset
4986 optimal_split_pos = min_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4987
a61af66fc99e Initial load
duke
parents:
diff changeset
4988 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4989 assert(min_split_pos < max_split_pos, "must be true then");
a61af66fc99e Initial load
duke
parents:
diff changeset
4990 assert(min_split_pos > 0, "cannot access min_split_pos - 1 otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
4991
a61af66fc99e Initial load
duke
parents:
diff changeset
4992 // reason for using min_split_pos - 1: when the minimal split pos is exactly at the
a61af66fc99e Initial load
duke
parents:
diff changeset
4993 // beginning of a block, then min_split_pos is also a possible split position.
a61af66fc99e Initial load
duke
parents:
diff changeset
4994 // Use the block before as min_block, because then min_block->last_lir_instruction_id() + 2 == min_split_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
4995 BlockBegin* min_block = allocator()->block_of_op_with_id(min_split_pos - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4996
a61af66fc99e Initial load
duke
parents:
diff changeset
4997 // reason for using max_split_pos - 1: otherwise there would be an assertion failure
a61af66fc99e Initial load
duke
parents:
diff changeset
4998 // when an interval ends at the end of the last block of the method
a61af66fc99e Initial load
duke
parents:
diff changeset
4999 // (in this case, max_split_pos == allocator()->max_lir_op_id() + 2, and there is no
a61af66fc99e Initial load
duke
parents:
diff changeset
5000 // block at this op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5001 BlockBegin* max_block = allocator()->block_of_op_with_id(max_split_pos - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5002
a61af66fc99e Initial load
duke
parents:
diff changeset
5003 assert(min_block->linear_scan_number() <= max_block->linear_scan_number(), "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5004 if (min_block == max_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5005 // split position cannot be moved to block boundary, so split as late as possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5006 TRACE_LINEAR_SCAN(4, tty->print_cr(" cannot move split pos to block boundary because min_pos and max_pos are in same block"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5007 optimal_split_pos = max_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5008
a61af66fc99e Initial load
duke
parents:
diff changeset
5009 } else if (it->has_hole_between(max_split_pos - 1, max_split_pos) && !allocator()->is_block_begin(max_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5010 // Do not move split position if the interval has a hole before max_split_pos.
a61af66fc99e Initial load
duke
parents:
diff changeset
5011 // Intervals resulting from Phi-Functions have more than one definition (marked
a61af66fc99e Initial load
duke
parents:
diff changeset
5012 // as mustHaveRegister) with a hole before each definition. When the register is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5013 // for the second definition, an earlier reloading is unnecessary.
a61af66fc99e Initial load
duke
parents:
diff changeset
5014 TRACE_LINEAR_SCAN(4, tty->print_cr(" interval has hole just before max_split_pos, so splitting at max_split_pos"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5015 optimal_split_pos = max_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5016
a61af66fc99e Initial load
duke
parents:
diff changeset
5017 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5018 // seach optimal block boundary between min_split_pos and max_split_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
5019 TRACE_LINEAR_SCAN(4, tty->print_cr(" moving split pos to optimal block boundary between block B%d and B%d", min_block->block_id(), max_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5020
a61af66fc99e Initial load
duke
parents:
diff changeset
5021 if (do_loop_optimization) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5022 // Loop optimization: if a loop-end marker is found between min- and max-position,
a61af66fc99e Initial load
duke
parents:
diff changeset
5023 // then split before this loop
a61af66fc99e Initial load
duke
parents:
diff changeset
5024 int loop_end_pos = it->next_usage_exact(loopEndMarker, min_block->last_lir_instruction_id() + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5025 TRACE_LINEAR_SCAN(4, tty->print_cr(" loop optimization: loop end found at pos %d", loop_end_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5026
a61af66fc99e Initial load
duke
parents:
diff changeset
5027 assert(loop_end_pos > min_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5028 if (loop_end_pos < max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5029 // loop-end marker found between min- and max-position
a61af66fc99e Initial load
duke
parents:
diff changeset
5030 // if it is not the end marker for the same loop as the min-position, then move
a61af66fc99e Initial load
duke
parents:
diff changeset
5031 // the max-position to this loop block.
a61af66fc99e Initial load
duke
parents:
diff changeset
5032 // Desired result: uses tagged as shouldHaveRegister inside a loop cause a reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
5033 // of the interval (normally, only mustHaveRegister causes a reloading)
a61af66fc99e Initial load
duke
parents:
diff changeset
5034 BlockBegin* loop_block = allocator()->block_of_op_with_id(loop_end_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5035
a61af66fc99e Initial load
duke
parents:
diff changeset
5036 TRACE_LINEAR_SCAN(4, tty->print_cr(" interval is used in loop that ends in block B%d, so trying to move max_block back from B%d to B%d", loop_block->block_id(), max_block->block_id(), loop_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5037 assert(loop_block != min_block, "loop_block and min_block must be different because block boundary is needed between");
a61af66fc99e Initial load
duke
parents:
diff changeset
5038
a61af66fc99e Initial load
duke
parents:
diff changeset
5039 optimal_split_pos = find_optimal_split_pos(min_block, loop_block, loop_block->last_lir_instruction_id() + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5040 if (optimal_split_pos == loop_block->last_lir_instruction_id() + 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5041 optimal_split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5042 TRACE_LINEAR_SCAN(4, tty->print_cr(" loop optimization not necessary"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5043 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5044 TRACE_LINEAR_SCAN(4, tty->print_cr(" loop optimization successful"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5045 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5046 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5047 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5048
a61af66fc99e Initial load
duke
parents:
diff changeset
5049 if (optimal_split_pos == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5050 // not calculated by loop optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
5051 optimal_split_pos = find_optimal_split_pos(min_block, max_block, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5052 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5053 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5054 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5055 TRACE_LINEAR_SCAN(4, tty->print_cr(" optimal split position: %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5056
a61af66fc99e Initial load
duke
parents:
diff changeset
5057 return optimal_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5058 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5059
a61af66fc99e Initial load
duke
parents:
diff changeset
5060
a61af66fc99e Initial load
duke
parents:
diff changeset
5061 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
5062 split an interval at the optimal position between min_split_pos and
a61af66fc99e Initial load
duke
parents:
diff changeset
5063 max_split_pos in two parts:
a61af66fc99e Initial load
duke
parents:
diff changeset
5064 1) the left part has already a location assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5065 2) the right part is sorted into to the unhandled-list
a61af66fc99e Initial load
duke
parents:
diff changeset
5066 */
a61af66fc99e Initial load
duke
parents:
diff changeset
5067 void LinearScanWalker::split_before_usage(Interval* it, int min_split_pos, int max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5068 TRACE_LINEAR_SCAN(2, tty->print ("----- splitting interval: "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5069 TRACE_LINEAR_SCAN(2, tty->print_cr(" between %d and %d", min_split_pos, max_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5070
a61af66fc99e Initial load
duke
parents:
diff changeset
5071 assert(it->from() < min_split_pos, "cannot split at start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5072 assert(current_position() < min_split_pos, "cannot split before current position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5073 assert(min_split_pos <= max_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5074 assert(max_split_pos <= it->to(), "cannot split after end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5075
a61af66fc99e Initial load
duke
parents:
diff changeset
5076 int optimal_split_pos = find_optimal_split_pos(it, min_split_pos, max_split_pos, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5077
a61af66fc99e Initial load
duke
parents:
diff changeset
5078 assert(min_split_pos <= optimal_split_pos && optimal_split_pos <= max_split_pos, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5079 assert(optimal_split_pos <= it->to(), "cannot split after end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5080 assert(optimal_split_pos > it->from(), "cannot split at start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5081
a61af66fc99e Initial load
duke
parents:
diff changeset
5082 if (optimal_split_pos == it->to() && it->next_usage(mustHaveRegister, min_split_pos) == max_jint) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5083 // the split position would be just before the end of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5084 // -> no split at all necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
5085 TRACE_LINEAR_SCAN(4, tty->print_cr(" no split necessary because optimal split position is at end of interval"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5086 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5087 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5088
a61af66fc99e Initial load
duke
parents:
diff changeset
5089 // must calculate this before the actual split is performed and before split position is moved to odd op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
5090 bool move_necessary = !allocator()->is_block_begin(optimal_split_pos) && !it->has_hole_between(optimal_split_pos - 1, optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5091
a61af66fc99e Initial load
duke
parents:
diff changeset
5092 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5093 // move position before actual instruction (odd op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5094 optimal_split_pos = (optimal_split_pos - 1) | 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5095 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5096
a61af66fc99e Initial load
duke
parents:
diff changeset
5097 TRACE_LINEAR_SCAN(4, tty->print_cr(" splitting at position %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5098 assert(allocator()->is_block_begin(optimal_split_pos) || (optimal_split_pos % 2 == 1), "split pos must be odd when not on block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
5099 assert(!allocator()->is_block_begin(optimal_split_pos) || (optimal_split_pos % 2 == 0), "split pos must be even on block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
5100
a61af66fc99e Initial load
duke
parents:
diff changeset
5101 Interval* split_part = it->split(optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5102
a61af66fc99e Initial load
duke
parents:
diff changeset
5103 allocator()->append_interval(split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5104 allocator()->copy_register_flags(it, split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5105 split_part->set_insert_move_when_activated(move_necessary);
a61af66fc99e Initial load
duke
parents:
diff changeset
5106 append_to_unhandled(unhandled_first_addr(anyKind), split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5107
a61af66fc99e Initial load
duke
parents:
diff changeset
5108 TRACE_LINEAR_SCAN(2, tty->print_cr(" split interval in two parts (insert_move_when_activated: %d)", move_necessary));
a61af66fc99e Initial load
duke
parents:
diff changeset
5109 TRACE_LINEAR_SCAN(2, tty->print (" "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5110 TRACE_LINEAR_SCAN(2, tty->print (" "); split_part->print());
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 split an interval at the optimal position between min_split_pos and
a61af66fc99e Initial load
duke
parents:
diff changeset
5115 max_split_pos in two parts:
a61af66fc99e Initial load
duke
parents:
diff changeset
5116 1) the left part has already a location assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5117 2) the right part is always on the stack and therefore ignored in further processing
a61af66fc99e Initial load
duke
parents:
diff changeset
5118 */
a61af66fc99e Initial load
duke
parents:
diff changeset
5119 void LinearScanWalker::split_for_spilling(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5120 // calculate allowed range of splitting position
a61af66fc99e Initial load
duke
parents:
diff changeset
5121 int max_split_pos = current_position();
a61af66fc99e Initial load
duke
parents:
diff changeset
5122 int min_split_pos = MAX2(it->previous_usage(shouldHaveRegister, max_split_pos) + 1, it->from());
a61af66fc99e Initial load
duke
parents:
diff changeset
5123
a61af66fc99e Initial load
duke
parents:
diff changeset
5124 TRACE_LINEAR_SCAN(2, tty->print ("----- splitting and spilling interval: "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5125 TRACE_LINEAR_SCAN(2, tty->print_cr(" between %d and %d", min_split_pos, max_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5126
a61af66fc99e Initial load
duke
parents:
diff changeset
5127 assert(it->state() == activeState, "why spill interval that is not active?");
a61af66fc99e Initial load
duke
parents:
diff changeset
5128 assert(it->from() <= min_split_pos, "cannot split before start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5129 assert(min_split_pos <= max_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5130 assert(max_split_pos < it->to(), "cannot split at end end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5131 assert(current_position() < it->to(), "interval must not end before current position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5132
a61af66fc99e Initial load
duke
parents:
diff changeset
5133 if (min_split_pos == it->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5134 // the whole interval is never used, so spill it entirely to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
5135 TRACE_LINEAR_SCAN(2, tty->print_cr(" spilling entire interval because split pos is at beginning of interval"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5136 assert(it->first_usage(shouldHaveRegister) > current_position(), "interval must not have use position before current_position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5137
a61af66fc99e Initial load
duke
parents:
diff changeset
5138 allocator()->assign_spill_slot(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5139 allocator()->change_spill_state(it, min_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5140
a61af66fc99e Initial load
duke
parents:
diff changeset
5141 // Also kick parent intervals out of register to memory when they have no use
a61af66fc99e Initial load
duke
parents:
diff changeset
5142 // position. This avoids short interval in register surrounded by intervals in
a61af66fc99e Initial load
duke
parents:
diff changeset
5143 // memory -> avoid useless moves from memory to register and back
a61af66fc99e Initial load
duke
parents:
diff changeset
5144 Interval* parent = it;
a61af66fc99e Initial load
duke
parents:
diff changeset
5145 while (parent != NULL && parent->is_split_child()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5146 parent = parent->split_child_before_op_id(parent->from());
a61af66fc99e Initial load
duke
parents:
diff changeset
5147
a61af66fc99e Initial load
duke
parents:
diff changeset
5148 if (parent->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5149 if (parent->first_usage(shouldHaveRegister) == max_jint) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5150 // parent is never used, so kick it out of its assigned register
a61af66fc99e Initial load
duke
parents:
diff changeset
5151 TRACE_LINEAR_SCAN(4, tty->print_cr(" kicking out interval %d out of its register because it is never used", parent->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5152 allocator()->assign_spill_slot(parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
5153 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5154 // do not go further back because the register is actually used by the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5155 parent = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
5156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5157 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5158 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5159
a61af66fc99e Initial load
duke
parents:
diff changeset
5160 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5161 // search optimal split pos, split interval and spill only the right hand part
a61af66fc99e Initial load
duke
parents:
diff changeset
5162 int optimal_split_pos = find_optimal_split_pos(it, min_split_pos, max_split_pos, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5163
a61af66fc99e Initial load
duke
parents:
diff changeset
5164 assert(min_split_pos <= optimal_split_pos && optimal_split_pos <= max_split_pos, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5165 assert(optimal_split_pos < it->to(), "cannot split at end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5166 assert(optimal_split_pos >= it->from(), "cannot split before start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5167
a61af66fc99e Initial load
duke
parents:
diff changeset
5168 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5169 // move position before actual instruction (odd op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5170 optimal_split_pos = (optimal_split_pos - 1) | 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5171 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5172
a61af66fc99e Initial load
duke
parents:
diff changeset
5173 TRACE_LINEAR_SCAN(4, tty->print_cr(" splitting at position %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5174 assert(allocator()->is_block_begin(optimal_split_pos) || (optimal_split_pos % 2 == 1), "split pos must be odd when not on block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
5175 assert(!allocator()->is_block_begin(optimal_split_pos) || (optimal_split_pos % 2 == 0), "split pos must be even on block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
5176
a61af66fc99e Initial load
duke
parents:
diff changeset
5177 Interval* spilled_part = it->split(optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5178 allocator()->append_interval(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5179 allocator()->assign_spill_slot(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5180 allocator()->change_spill_state(spilled_part, optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5181
a61af66fc99e Initial load
duke
parents:
diff changeset
5182 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5183 TRACE_LINEAR_SCAN(4, tty->print_cr(" inserting move from interval %d to %d", it->reg_num(), spilled_part->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5184 insert_move(optimal_split_pos, it, spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5186
a61af66fc99e Initial load
duke
parents:
diff changeset
5187 // the current_split_child is needed later when moves are inserted for reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
5188 assert(spilled_part->current_split_child() == it, "overwriting wrong current_split_child");
a61af66fc99e Initial load
duke
parents:
diff changeset
5189 spilled_part->make_current_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
5190
a61af66fc99e Initial load
duke
parents:
diff changeset
5191 TRACE_LINEAR_SCAN(2, tty->print_cr(" split interval in two parts"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5192 TRACE_LINEAR_SCAN(2, tty->print (" "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5193 TRACE_LINEAR_SCAN(2, tty->print (" "); spilled_part->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5194 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5195 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5196
a61af66fc99e Initial load
duke
parents:
diff changeset
5197
a61af66fc99e Initial load
duke
parents:
diff changeset
5198 void LinearScanWalker::split_stack_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5199 int min_split_pos = current_position() + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5200 int max_split_pos = MIN2(it->first_usage(shouldHaveRegister), it->to());
a61af66fc99e Initial load
duke
parents:
diff changeset
5201
a61af66fc99e Initial load
duke
parents:
diff changeset
5202 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5204
a61af66fc99e Initial load
duke
parents:
diff changeset
5205 void LinearScanWalker::split_when_partial_register_available(Interval* it, int register_available_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5206 int min_split_pos = MAX2(it->previous_usage(shouldHaveRegister, register_available_until), it->from() + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5207 int max_split_pos = register_available_until;
a61af66fc99e Initial load
duke
parents:
diff changeset
5208
a61af66fc99e Initial load
duke
parents:
diff changeset
5209 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5210 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5211
a61af66fc99e Initial load
duke
parents:
diff changeset
5212 void LinearScanWalker::split_and_spill_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5213 assert(it->state() == activeState || it->state() == inactiveState, "other states not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
5214
a61af66fc99e Initial load
duke
parents:
diff changeset
5215 int current_pos = current_position();
a61af66fc99e Initial load
duke
parents:
diff changeset
5216 if (it->state() == inactiveState) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5217 // the interval is currently inactive, so no spill slot is needed for now.
a61af66fc99e Initial load
duke
parents:
diff changeset
5218 // when the split part is activated, the interval has a new chance to get a register,
a61af66fc99e Initial load
duke
parents:
diff changeset
5219 // so in the best case no stack slot is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
5220 assert(it->has_hole_between(current_pos - 1, current_pos + 1), "interval can not be inactive otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5221 split_before_usage(it, current_pos + 1, current_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5222
a61af66fc99e Initial load
duke
parents:
diff changeset
5223 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5224 // search the position where the interval must have a register and split
a61af66fc99e Initial load
duke
parents:
diff changeset
5225 // at the optimal position before.
a61af66fc99e Initial load
duke
parents:
diff changeset
5226 // The new created part is added to the unhandled list and will get a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5227 // when it is activated
a61af66fc99e Initial load
duke
parents:
diff changeset
5228 int min_split_pos = current_pos + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5229 int max_split_pos = MIN2(it->next_usage(mustHaveRegister, min_split_pos), it->to());
a61af66fc99e Initial load
duke
parents:
diff changeset
5230
a61af66fc99e Initial load
duke
parents:
diff changeset
5231 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5232
a61af66fc99e Initial load
duke
parents:
diff changeset
5233 assert(it->next_usage(mustHaveRegister, current_pos) == max_jint, "the remaining part is spilled to stack and therefore has no register");
a61af66fc99e Initial load
duke
parents:
diff changeset
5234 split_for_spilling(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5235 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5237
a61af66fc99e Initial load
duke
parents:
diff changeset
5238
a61af66fc99e Initial load
duke
parents:
diff changeset
5239 int LinearScanWalker::find_free_reg(int reg_needed_until, int interval_to, int hint_reg, int ignore_reg, bool* need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5240 int min_full_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5241 int max_partial_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5242
a61af66fc99e Initial load
duke
parents:
diff changeset
5243 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5244 if (i == ignore_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5245 // this register must be ignored
a61af66fc99e Initial load
duke
parents:
diff changeset
5246
a61af66fc99e Initial load
duke
parents:
diff changeset
5247 } else if (_use_pos[i] >= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5248 // this register is free for the full interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5249 if (min_full_reg == any_reg || i == hint_reg || (_use_pos[i] < _use_pos[min_full_reg] && min_full_reg != hint_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5250 min_full_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5252 } else if (_use_pos[i] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5253 // this register is at least free until reg_needed_until
a61af66fc99e Initial load
duke
parents:
diff changeset
5254 if (max_partial_reg == any_reg || i == hint_reg || (_use_pos[i] > _use_pos[max_partial_reg] && max_partial_reg != hint_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5255 max_partial_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5256 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5258 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5259
a61af66fc99e Initial load
duke
parents:
diff changeset
5260 if (min_full_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5261 return min_full_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5262 } else if (max_partial_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5263 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5264 return max_partial_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5265 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5266 return any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5267 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5268 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5269
a61af66fc99e Initial load
duke
parents:
diff changeset
5270 int LinearScanWalker::find_free_double_reg(int reg_needed_until, int interval_to, int hint_reg, bool* need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5271 assert((_last_reg - _first_reg + 1) % 2 == 0, "adjust algorithm");
a61af66fc99e Initial load
duke
parents:
diff changeset
5272
a61af66fc99e Initial load
duke
parents:
diff changeset
5273 int min_full_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5274 int max_partial_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5275
a61af66fc99e Initial load
duke
parents:
diff changeset
5276 for (int i = _first_reg; i < _last_reg; i+=2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5277 if (_use_pos[i] >= interval_to && _use_pos[i + 1] >= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5278 // this register is free for the full interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5279 if (min_full_reg == any_reg || i == hint_reg || (_use_pos[i] < _use_pos[min_full_reg] && min_full_reg != hint_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5280 min_full_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5281 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5282 } else if (_use_pos[i] > reg_needed_until && _use_pos[i + 1] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5283 // this register is at least free until reg_needed_until
a61af66fc99e Initial load
duke
parents:
diff changeset
5284 if (max_partial_reg == any_reg || i == hint_reg || (_use_pos[i] > _use_pos[max_partial_reg] && max_partial_reg != hint_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5285 max_partial_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5286 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5287 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5288 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5289
a61af66fc99e Initial load
duke
parents:
diff changeset
5290 if (min_full_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5291 return min_full_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5292 } else if (max_partial_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5293 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5294 return max_partial_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5295 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5296 return any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5297 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5298 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5299
a61af66fc99e Initial load
duke
parents:
diff changeset
5300
a61af66fc99e Initial load
duke
parents:
diff changeset
5301 bool LinearScanWalker::alloc_free_reg(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5302 TRACE_LINEAR_SCAN(2, tty->print("trying to find free register for "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5303
a61af66fc99e Initial load
duke
parents:
diff changeset
5304 init_use_lists(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5305 free_exclude_active_fixed();
a61af66fc99e Initial load
duke
parents:
diff changeset
5306 free_exclude_active_any();
a61af66fc99e Initial load
duke
parents:
diff changeset
5307 free_collect_inactive_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5308 free_collect_inactive_any(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5309 // free_collect_unhandled(fixedKind, cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5310 assert(unhandled_first(fixedKind) == Interval::end(), "must not have unhandled fixed intervals because all fixed intervals have a use at position 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
5311
a61af66fc99e Initial load
duke
parents:
diff changeset
5312 // _use_pos contains the start of the next interval that has this register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5313 // (either as a fixed register or a normal allocated register in the past)
a61af66fc99e Initial load
duke
parents:
diff changeset
5314 // only intervals overlapping with cur are processed, non-overlapping invervals can be ignored safely
a61af66fc99e Initial load
duke
parents:
diff changeset
5315 TRACE_LINEAR_SCAN(4, tty->print_cr(" state of registers:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5316 TRACE_LINEAR_SCAN(4, for (int i = _first_reg; i <= _last_reg; i++) tty->print_cr(" reg %d: use_pos: %d", i, _use_pos[i]));
a61af66fc99e Initial load
duke
parents:
diff changeset
5317
a61af66fc99e Initial load
duke
parents:
diff changeset
5318 int hint_reg, hint_regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5319 Interval* register_hint = cur->register_hint();
a61af66fc99e Initial load
duke
parents:
diff changeset
5320 if (register_hint != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5321 hint_reg = register_hint->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
5322 hint_regHi = register_hint->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
5323
a61af66fc99e Initial load
duke
parents:
diff changeset
5324 if (allocator()->is_precolored_cpu_interval(register_hint)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5325 assert(hint_reg != any_reg && hint_regHi == any_reg, "must be for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
5326 hint_regHi = hint_reg + 1; // connect e.g. eax-edx
a61af66fc99e Initial load
duke
parents:
diff changeset
5327 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5328 TRACE_LINEAR_SCAN(4, tty->print(" hint registers %d, %d from interval ", hint_reg, hint_regHi); register_hint->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5329
a61af66fc99e Initial load
duke
parents:
diff changeset
5330 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5331 hint_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5332 hint_regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5333 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5334 assert(hint_reg == any_reg || hint_reg != hint_regHi, "hint reg and regHi equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
5335 assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned to interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5336
a61af66fc99e Initial load
duke
parents:
diff changeset
5337 // the register must be free at least until this position
a61af66fc99e Initial load
duke
parents:
diff changeset
5338 int reg_needed_until = cur->from() + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5339 int interval_to = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5340
a61af66fc99e Initial load
duke
parents:
diff changeset
5341 bool need_split = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5342 int split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5343 int reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5344 int regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5345
a61af66fc99e Initial load
duke
parents:
diff changeset
5346 if (_adjacent_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5347 reg = find_free_double_reg(reg_needed_until, interval_to, hint_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5348 regHi = reg + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5349 if (reg == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5350 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5351 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5352 split_pos = MIN2(_use_pos[reg], _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5353
a61af66fc99e Initial load
duke
parents:
diff changeset
5354 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5355 reg = find_free_reg(reg_needed_until, interval_to, hint_reg, any_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5356 if (reg == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5357 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5358 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5359 split_pos = _use_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5360
a61af66fc99e Initial load
duke
parents:
diff changeset
5361 if (_num_phys_regs == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5362 regHi = find_free_reg(reg_needed_until, interval_to, hint_regHi, reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5363
a61af66fc99e Initial load
duke
parents:
diff changeset
5364 if (_use_pos[reg] < interval_to && regHi == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5365 // do not split interval if only one register can be assigned until the split pos
a61af66fc99e Initial load
duke
parents:
diff changeset
5366 // (when one register is found for the whole interval, split&spill is only
a61af66fc99e Initial load
duke
parents:
diff changeset
5367 // performed for the hi register)
a61af66fc99e Initial load
duke
parents:
diff changeset
5368 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5369
a61af66fc99e Initial load
duke
parents:
diff changeset
5370 } else if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5371 split_pos = MIN2(split_pos, _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5372
a61af66fc99e Initial load
duke
parents:
diff changeset
5373 // sort register numbers to prevent e.g. a move from eax,ebx to ebx,eax
a61af66fc99e Initial load
duke
parents:
diff changeset
5374 if (reg > regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5375 int temp = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5376 reg = regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5377 regHi = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
5378 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5379 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5380 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5381 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5382
a61af66fc99e Initial load
duke
parents:
diff changeset
5383 cur->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5384 TRACE_LINEAR_SCAN(2, tty->print_cr("selected register %d, %d", reg, regHi));
a61af66fc99e Initial load
duke
parents:
diff changeset
5385
a61af66fc99e Initial load
duke
parents:
diff changeset
5386 assert(split_pos > 0, "invalid split_pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
5387 if (need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5388 // register not available for full interval, so split it
a61af66fc99e Initial load
duke
parents:
diff changeset
5389 split_when_partial_register_available(cur, split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5390 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5391
a61af66fc99e Initial load
duke
parents:
diff changeset
5392 // only return true if interval is completely assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5393 return _num_phys_regs == 1 || regHi != any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5394 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5395
a61af66fc99e Initial load
duke
parents:
diff changeset
5396
a61af66fc99e Initial load
duke
parents:
diff changeset
5397 int LinearScanWalker::find_locked_reg(int reg_needed_until, int interval_to, int hint_reg, int ignore_reg, bool* need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5398 int max_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5399
a61af66fc99e Initial load
duke
parents:
diff changeset
5400 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5401 if (i == ignore_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5402 // this register must be ignored
a61af66fc99e Initial load
duke
parents:
diff changeset
5403
a61af66fc99e Initial load
duke
parents:
diff changeset
5404 } else if (_use_pos[i] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5405 if (max_reg == any_reg || i == hint_reg || (_use_pos[i] > _use_pos[max_reg] && max_reg != hint_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5406 max_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5407 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5408 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5409 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5410
a61af66fc99e Initial load
duke
parents:
diff changeset
5411 if (max_reg != any_reg && _block_pos[max_reg] <= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5412 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5413 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5414
a61af66fc99e Initial load
duke
parents:
diff changeset
5415 return max_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5416 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5417
a61af66fc99e Initial load
duke
parents:
diff changeset
5418 int LinearScanWalker::find_locked_double_reg(int reg_needed_until, int interval_to, int hint_reg, bool* need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5419 assert((_last_reg - _first_reg + 1) % 2 == 0, "adjust algorithm");
a61af66fc99e Initial load
duke
parents:
diff changeset
5420
a61af66fc99e Initial load
duke
parents:
diff changeset
5421 int max_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5422
a61af66fc99e Initial load
duke
parents:
diff changeset
5423 for (int i = _first_reg; i < _last_reg; i+=2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5424 if (_use_pos[i] > reg_needed_until && _use_pos[i + 1] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5425 if (max_reg == any_reg || _use_pos[i] > _use_pos[max_reg]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5426 max_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5427 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5428 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5430
a61af66fc99e Initial load
duke
parents:
diff changeset
5431 if (_block_pos[max_reg] <= interval_to || _block_pos[max_reg + 1] <= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5432 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5433 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5434
a61af66fc99e Initial load
duke
parents:
diff changeset
5435 return max_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5436 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5437
a61af66fc99e Initial load
duke
parents:
diff changeset
5438 void LinearScanWalker::split_and_spill_intersecting_intervals(int reg, int regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5439 assert(reg != any_reg, "no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5440
a61af66fc99e Initial load
duke
parents:
diff changeset
5441 for (int i = 0; i < _spill_intervals[reg]->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5442 Interval* it = _spill_intervals[reg]->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5443 remove_from_list(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5444 split_and_spill_interval(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5445 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5446
a61af66fc99e Initial load
duke
parents:
diff changeset
5447 if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5448 IntervalList* processed = _spill_intervals[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5449 for (int i = 0; i < _spill_intervals[regHi]->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5450 Interval* it = _spill_intervals[regHi]->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5451 if (processed->index_of(it) == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5452 remove_from_list(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5453 split_and_spill_interval(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5454 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5455 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5456 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5457 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5458
a61af66fc99e Initial load
duke
parents:
diff changeset
5459
a61af66fc99e Initial load
duke
parents:
diff changeset
5460 // Split an Interval and spill it to memory so that cur can be placed in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5461 void LinearScanWalker::alloc_locked_reg(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5462 TRACE_LINEAR_SCAN(2, tty->print("need to split and spill to get register for "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5463
a61af66fc99e Initial load
duke
parents:
diff changeset
5464 // collect current usage of registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5465 init_use_lists(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5466 spill_exclude_active_fixed();
a61af66fc99e Initial load
duke
parents:
diff changeset
5467 // spill_block_unhandled_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5468 assert(unhandled_first(fixedKind) == Interval::end(), "must not have unhandled fixed intervals because all fixed intervals have a use at position 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
5469 spill_block_inactive_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5470 spill_collect_active_any();
a61af66fc99e Initial load
duke
parents:
diff changeset
5471 spill_collect_inactive_any(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5472
a61af66fc99e Initial load
duke
parents:
diff changeset
5473 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
5474 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5475 tty->print_cr(" state of registers:");
a61af66fc99e Initial load
duke
parents:
diff changeset
5476 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5477 tty->print(" reg %d: use_pos: %d, block_pos: %d, intervals: ", i, _use_pos[i], _block_pos[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5478 for (int j = 0; j < _spill_intervals[i]->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5479 tty->print("%d ", _spill_intervals[i]->at(j)->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
5480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5481 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5483 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5484 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5485
a61af66fc99e Initial load
duke
parents:
diff changeset
5486 // the register must be free at least until this position
a61af66fc99e Initial load
duke
parents:
diff changeset
5487 int reg_needed_until = MIN2(cur->first_usage(mustHaveRegister), cur->from() + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5488 int interval_to = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5489 assert (reg_needed_until > 0 && reg_needed_until < max_jint, "interval has no use");
a61af66fc99e Initial load
duke
parents:
diff changeset
5490
a61af66fc99e Initial load
duke
parents:
diff changeset
5491 int split_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
5492 int use_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
5493 bool need_split = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5494 int reg, regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5495
a61af66fc99e Initial load
duke
parents:
diff changeset
5496 if (_adjacent_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5497 reg = find_locked_double_reg(reg_needed_until, interval_to, any_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5498 regHi = reg + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5499
a61af66fc99e Initial load
duke
parents:
diff changeset
5500 if (reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5501 use_pos = MIN2(_use_pos[reg], _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5502 split_pos = MIN2(_block_pos[reg], _block_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5503 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5504 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5505 reg = find_locked_reg(reg_needed_until, interval_to, any_reg, cur->assigned_reg(), &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5506 regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5507
a61af66fc99e Initial load
duke
parents:
diff changeset
5508 if (reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5509 use_pos = _use_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5510 split_pos = _block_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5511
a61af66fc99e Initial load
duke
parents:
diff changeset
5512 if (_num_phys_regs == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5513 if (cur->assigned_reg() != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5514 regHi = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5515 reg = cur->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
5516 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5517 regHi = find_locked_reg(reg_needed_until, interval_to, any_reg, reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5518 if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5519 use_pos = MIN2(use_pos, _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5520 split_pos = MIN2(split_pos, _block_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5521 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5522 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5523
a61af66fc99e Initial load
duke
parents:
diff changeset
5524 if (regHi != any_reg && reg > regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5525 // sort register numbers to prevent e.g. a move from eax,ebx to ebx,eax
a61af66fc99e Initial load
duke
parents:
diff changeset
5526 int temp = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5527 reg = regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5528 regHi = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
5529 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5530 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5531 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5532 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5533
a61af66fc99e Initial load
duke
parents:
diff changeset
5534 if (reg == any_reg || (_num_phys_regs == 2 && regHi == any_reg) || use_pos <= cur->first_usage(mustHaveRegister)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5535 // the first use of cur is later than the spilling position -> spill cur
a61af66fc99e Initial load
duke
parents:
diff changeset
5536 TRACE_LINEAR_SCAN(4, tty->print_cr("able to spill current interval. first_usage(register): %d, use_pos: %d", cur->first_usage(mustHaveRegister), use_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5537
a61af66fc99e Initial load
duke
parents:
diff changeset
5538 if (cur->first_usage(mustHaveRegister) <= cur->from() + 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5539 assert(false, "cannot spill interval that is used in first instruction (possible reason: no register found)");
a61af66fc99e Initial load
duke
parents:
diff changeset
5540 // assign a reasonable register and do a bailout in product mode to avoid errors
a61af66fc99e Initial load
duke
parents:
diff changeset
5541 allocator()->assign_spill_slot(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5542 BAILOUT("LinearScan: no register found");
a61af66fc99e Initial load
duke
parents:
diff changeset
5543 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5544
a61af66fc99e Initial load
duke
parents:
diff changeset
5545 split_and_spill_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5546 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5547 TRACE_LINEAR_SCAN(4, tty->print_cr("decided to use register %d, %d", reg, regHi));
a61af66fc99e Initial load
duke
parents:
diff changeset
5548 assert(reg != any_reg && (_num_phys_regs == 1 || regHi != any_reg), "no register found");
a61af66fc99e Initial load
duke
parents:
diff changeset
5549 assert(split_pos > 0, "invalid split_pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
5550 assert(need_split == false || split_pos > cur->from(), "splitting interval at from");
a61af66fc99e Initial load
duke
parents:
diff changeset
5551
a61af66fc99e Initial load
duke
parents:
diff changeset
5552 cur->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5553 if (need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5554 // register not available for full interval, so split it
a61af66fc99e Initial load
duke
parents:
diff changeset
5555 split_when_partial_register_available(cur, split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5556 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5557
a61af66fc99e Initial load
duke
parents:
diff changeset
5558 // perform splitting and spilling for all affected intervalls
a61af66fc99e Initial load
duke
parents:
diff changeset
5559 split_and_spill_intersecting_intervals(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5560 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5561 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5562
a61af66fc99e Initial load
duke
parents:
diff changeset
5563 bool LinearScanWalker::no_allocation_possible(Interval* cur) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
5564 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
5565 // fast calculation of intervals that can never get a register because the
a61af66fc99e Initial load
duke
parents:
diff changeset
5566 // the next instruction is a call that blocks all registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5567 // Note: this does not work if callee-saved registers are available (e.g. on Sparc)
a61af66fc99e Initial load
duke
parents:
diff changeset
5568
a61af66fc99e Initial load
duke
parents:
diff changeset
5569 // check if this interval is the result of a split operation
a61af66fc99e Initial load
duke
parents:
diff changeset
5570 // (an interval got a register until this position)
a61af66fc99e Initial load
duke
parents:
diff changeset
5571 int pos = cur->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
5572 if ((pos & 1) == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5573 // the current instruction is a call that blocks all registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5574 if (pos < allocator()->max_lir_op_id() && allocator()->has_call(pos + 1)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5575 TRACE_LINEAR_SCAN(4, tty->print_cr(" free register cannot be available because all registers blocked by following call"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5576
a61af66fc99e Initial load
duke
parents:
diff changeset
5577 // safety check that there is really no register available
a61af66fc99e Initial load
duke
parents:
diff changeset
5578 assert(alloc_free_reg(cur) == false, "found a register for this interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5579 return true;
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 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5584 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5585 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5586
a61af66fc99e Initial load
duke
parents:
diff changeset
5587 void LinearScanWalker::init_vars_for_alloc(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5588 BasicType type = cur->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
5589 _num_phys_regs = LinearScan::num_physical_regs(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
5590 _adjacent_regs = LinearScan::requires_adjacent_regs(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
5591
a61af66fc99e Initial load
duke
parents:
diff changeset
5592 if (pd_init_regs_for_alloc(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5593 // the appropriate register range was selected.
a61af66fc99e Initial load
duke
parents:
diff changeset
5594 } else if (type == T_FLOAT || type == T_DOUBLE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5595 _first_reg = pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5596 _last_reg = pd_last_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5597 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5598 _first_reg = pd_first_cpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5599 _last_reg = pd_last_cpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5600 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5601
a61af66fc99e Initial load
duke
parents:
diff changeset
5602 assert(0 <= _first_reg && _first_reg < LinearScan::nof_regs, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5603 assert(0 <= _last_reg && _last_reg < LinearScan::nof_regs, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5604 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5605
a61af66fc99e Initial load
duke
parents:
diff changeset
5606
a61af66fc99e Initial load
duke
parents:
diff changeset
5607 bool LinearScanWalker::is_move(LIR_Op* op, Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5608 if (op->code() != lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5609 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5610 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5611 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5612
a61af66fc99e Initial load
duke
parents:
diff changeset
5613 LIR_Opr in = ((LIR_Op1*)op)->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5614 LIR_Opr res = ((LIR_Op1*)op)->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5615 return in->is_virtual() && res->is_virtual() && in->vreg_number() == from->reg_num() && res->vreg_number() == to->reg_num();
a61af66fc99e Initial load
duke
parents:
diff changeset
5616 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5617
a61af66fc99e Initial load
duke
parents:
diff changeset
5618 // optimization (especially for phi functions of nested loops):
a61af66fc99e Initial load
duke
parents:
diff changeset
5619 // assign same spill slot to non-intersecting intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
5620 void LinearScanWalker::combine_spilled_intervals(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5621 if (cur->is_split_child()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5622 // optimization is only suitable for split parents
a61af66fc99e Initial load
duke
parents:
diff changeset
5623 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5624 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5625
a61af66fc99e Initial load
duke
parents:
diff changeset
5626 Interval* register_hint = cur->register_hint(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5627 if (register_hint == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5628 // cur is not the target of a move, otherwise register_hint would be set
a61af66fc99e Initial load
duke
parents:
diff changeset
5629 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5630 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5631 assert(register_hint->is_split_parent(), "register hint must be split parent");
a61af66fc99e Initial load
duke
parents:
diff changeset
5632
a61af66fc99e Initial load
duke
parents:
diff changeset
5633 if (cur->spill_state() != noOptimization || register_hint->spill_state() != noOptimization) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5634 // combining the stack slots for intervals where spill move optimization is applied
a61af66fc99e Initial load
duke
parents:
diff changeset
5635 // is not benefitial and would cause problems
a61af66fc99e Initial load
duke
parents:
diff changeset
5636 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5637 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5638
a61af66fc99e Initial load
duke
parents:
diff changeset
5639 int begin_pos = cur->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
5640 int end_pos = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5641 if (end_pos > allocator()->max_lir_op_id() || (begin_pos & 1) != 0 || (end_pos & 1) != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5642 // safety check that lir_op_with_id is allowed
a61af66fc99e Initial load
duke
parents:
diff changeset
5643 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5645
a61af66fc99e Initial load
duke
parents:
diff changeset
5646 if (!is_move(allocator()->lir_op_with_id(begin_pos), register_hint, cur) || !is_move(allocator()->lir_op_with_id(end_pos), cur, register_hint)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5647 // cur and register_hint are not connected with two moves
a61af66fc99e Initial load
duke
parents:
diff changeset
5648 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5649 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5650
a61af66fc99e Initial load
duke
parents:
diff changeset
5651 Interval* begin_hint = register_hint->split_child_at_op_id(begin_pos, LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
5652 Interval* end_hint = register_hint->split_child_at_op_id(end_pos, LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
5653 if (begin_hint == end_hint || begin_hint->to() != begin_pos || end_hint->from() != end_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5654 // register_hint must be split, otherwise the re-writing of use positions does not work
a61af66fc99e Initial load
duke
parents:
diff changeset
5655 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5656 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5657
a61af66fc99e Initial load
duke
parents:
diff changeset
5658 assert(begin_hint->assigned_reg() != any_reg, "must have register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5659 assert(end_hint->assigned_reg() == any_reg, "must not have register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5660 assert(cur->first_usage(mustHaveRegister) == begin_pos, "must have use position at begin of interval because of move");
a61af66fc99e Initial load
duke
parents:
diff changeset
5661 assert(end_hint->first_usage(mustHaveRegister) == end_pos, "must have use position at begin of interval because of move");
a61af66fc99e Initial load
duke
parents:
diff changeset
5662
a61af66fc99e Initial load
duke
parents:
diff changeset
5663 if (begin_hint->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5664 // register_hint is not spilled at begin_pos, so it would not be benefitial to immediately spill cur
a61af66fc99e Initial load
duke
parents:
diff changeset
5665 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5666 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5667 assert(register_hint->canonical_spill_slot() != -1, "must be set when part of interval was spilled");
a61af66fc99e Initial load
duke
parents:
diff changeset
5668
a61af66fc99e Initial load
duke
parents:
diff changeset
5669 // modify intervals such that cur gets the same stack slot as register_hint
a61af66fc99e Initial load
duke
parents:
diff changeset
5670 // delete use positions to prevent the intervals to get a register at beginning
a61af66fc99e Initial load
duke
parents:
diff changeset
5671 cur->set_canonical_spill_slot(register_hint->canonical_spill_slot());
a61af66fc99e Initial load
duke
parents:
diff changeset
5672 cur->remove_first_use_pos();
a61af66fc99e Initial load
duke
parents:
diff changeset
5673 end_hint->remove_first_use_pos();
a61af66fc99e Initial load
duke
parents:
diff changeset
5674 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5675
a61af66fc99e Initial load
duke
parents:
diff changeset
5676
a61af66fc99e Initial load
duke
parents:
diff changeset
5677 // allocate a physical register or memory location to an interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5678 bool LinearScanWalker::activate_current() {
a61af66fc99e Initial load
duke
parents:
diff changeset
5679 Interval* cur = current();
a61af66fc99e Initial load
duke
parents:
diff changeset
5680 bool result = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5681
a61af66fc99e Initial load
duke
parents:
diff changeset
5682 TRACE_LINEAR_SCAN(2, tty->print ("+++++ activating interval "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5683 TRACE_LINEAR_SCAN(4, tty->print_cr(" split_parent: %d, insert_move_when_activated: %d", cur->split_parent()->reg_num(), cur->insert_move_when_activated()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5684
a61af66fc99e Initial load
duke
parents:
diff changeset
5685 if (cur->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5686 // activating an interval that has a stack slot assigned -> split it at first use position
a61af66fc99e Initial load
duke
parents:
diff changeset
5687 // used for method parameters
a61af66fc99e Initial load
duke
parents:
diff changeset
5688 TRACE_LINEAR_SCAN(4, tty->print_cr(" interval has spill slot assigned (method parameter) -> split it before first use"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5689
a61af66fc99e Initial load
duke
parents:
diff changeset
5690 split_stack_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5691 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5692
a61af66fc99e Initial load
duke
parents:
diff changeset
5693 } else if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::must_start_in_memory)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5694 // activating an interval that must start in a stack slot, but may get a register later
a61af66fc99e Initial load
duke
parents:
diff changeset
5695 // used for lir_roundfp: rounding is done by store to stack and reload later
a61af66fc99e Initial load
duke
parents:
diff changeset
5696 TRACE_LINEAR_SCAN(4, tty->print_cr(" interval must start in stack slot -> split it before first use"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5697 assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5698
a61af66fc99e Initial load
duke
parents:
diff changeset
5699 allocator()->assign_spill_slot(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5700 split_stack_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5701 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5702
a61af66fc99e Initial load
duke
parents:
diff changeset
5703 } else if (cur->assigned_reg() == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5704 // interval has not assigned register -> normal allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
5705 // (this is the normal case for most intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
5706 TRACE_LINEAR_SCAN(4, tty->print_cr(" normal allocation of register"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5707
a61af66fc99e Initial load
duke
parents:
diff changeset
5708 // assign same spill slot to non-intersecting intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
5709 combine_spilled_intervals(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5710
a61af66fc99e Initial load
duke
parents:
diff changeset
5711 init_vars_for_alloc(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5712 if (no_allocation_possible(cur) || !alloc_free_reg(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5713 // no empty register available.
a61af66fc99e Initial load
duke
parents:
diff changeset
5714 // split and spill another interval so that this interval gets a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5715 alloc_locked_reg(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5716 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5717
a61af66fc99e Initial load
duke
parents:
diff changeset
5718 // spilled intervals need not be move to active-list
a61af66fc99e Initial load
duke
parents:
diff changeset
5719 if (cur->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5720 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5721 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5722 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5723
a61af66fc99e Initial load
duke
parents:
diff changeset
5724 // load spilled values that become active from stack slot to register
a61af66fc99e Initial load
duke
parents:
diff changeset
5725 if (cur->insert_move_when_activated()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5726 assert(cur->is_split_child(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
5727 assert(cur->current_split_child() != NULL, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
5728 assert(cur->current_split_child()->reg_num() != cur->reg_num(), "cannot insert move between same interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5729 TRACE_LINEAR_SCAN(4, tty->print_cr("Inserting move from interval %d to %d because insert_move_when_activated is set", cur->current_split_child()->reg_num(), cur->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5730
a61af66fc99e Initial load
duke
parents:
diff changeset
5731 insert_move(cur->from(), cur->current_split_child(), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5732 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5733 cur->make_current_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
5734
a61af66fc99e Initial load
duke
parents:
diff changeset
5735 return result; // true = interval is moved to active list
a61af66fc99e Initial load
duke
parents:
diff changeset
5736 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5737
a61af66fc99e Initial load
duke
parents:
diff changeset
5738
a61af66fc99e Initial load
duke
parents:
diff changeset
5739 // Implementation of EdgeMoveOptimizer
a61af66fc99e Initial load
duke
parents:
diff changeset
5740
a61af66fc99e Initial load
duke
parents:
diff changeset
5741 EdgeMoveOptimizer::EdgeMoveOptimizer() :
a61af66fc99e Initial load
duke
parents:
diff changeset
5742 _edge_instructions(4),
a61af66fc99e Initial load
duke
parents:
diff changeset
5743 _edge_instructions_idx(4)
a61af66fc99e Initial load
duke
parents:
diff changeset
5744 {
a61af66fc99e Initial load
duke
parents:
diff changeset
5745 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5746
a61af66fc99e Initial load
duke
parents:
diff changeset
5747 void EdgeMoveOptimizer::optimize(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5748 EdgeMoveOptimizer optimizer = EdgeMoveOptimizer();
a61af66fc99e Initial load
duke
parents:
diff changeset
5749
a61af66fc99e Initial load
duke
parents:
diff changeset
5750 // ignore the first block in the list (index 0 is not processed)
a61af66fc99e Initial load
duke
parents:
diff changeset
5751 for (int i = code->length() - 1; i >= 1; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5752 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5753
a61af66fc99e Initial load
duke
parents:
diff changeset
5754 if (block->number_of_preds() > 1 && !block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5755 optimizer.optimize_moves_at_block_end(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
5756 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5757 if (block->number_of_sux() == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5758 optimizer.optimize_moves_at_block_begin(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
5759 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5760 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5761 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5762
a61af66fc99e Initial load
duke
parents:
diff changeset
5763
a61af66fc99e Initial load
duke
parents:
diff changeset
5764 // clear all internal data structures
a61af66fc99e Initial load
duke
parents:
diff changeset
5765 void EdgeMoveOptimizer::init_instructions() {
a61af66fc99e Initial load
duke
parents:
diff changeset
5766 _edge_instructions.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
5767 _edge_instructions_idx.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
5768 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5769
a61af66fc99e Initial load
duke
parents:
diff changeset
5770 // append a lir-instruction-list and the index of the current operation in to the list
a61af66fc99e Initial load
duke
parents:
diff changeset
5771 void EdgeMoveOptimizer::append_instructions(LIR_OpList* instructions, int instructions_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5772 _edge_instructions.append(instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
5773 _edge_instructions_idx.append(instructions_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5774 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5775
a61af66fc99e Initial load
duke
parents:
diff changeset
5776 // return the current operation of the given edge (predecessor or successor)
a61af66fc99e Initial load
duke
parents:
diff changeset
5777 LIR_Op* EdgeMoveOptimizer::instruction_at(int edge) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5778 LIR_OpList* instructions = _edge_instructions.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5779 int idx = _edge_instructions_idx.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5780
a61af66fc99e Initial load
duke
parents:
diff changeset
5781 if (idx < instructions->length()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5782 return instructions->at(idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5783 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5784 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
5785 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5786 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5787
a61af66fc99e Initial load
duke
parents:
diff changeset
5788 // removes the current operation of the given edge (predecessor or successor)
a61af66fc99e Initial load
duke
parents:
diff changeset
5789 void EdgeMoveOptimizer::remove_cur_instruction(int edge, bool decrement_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5790 LIR_OpList* instructions = _edge_instructions.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5791 int idx = _edge_instructions_idx.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5792 instructions->remove_at(idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5793
a61af66fc99e Initial load
duke
parents:
diff changeset
5794 if (decrement_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5795 _edge_instructions_idx.at_put(edge, idx - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5796 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5797 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5798
a61af66fc99e Initial load
duke
parents:
diff changeset
5799
a61af66fc99e Initial load
duke
parents:
diff changeset
5800 bool EdgeMoveOptimizer::operations_different(LIR_Op* op1, LIR_Op* op2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5801 if (op1 == NULL || op2 == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5802 // at least one block is already empty -> no optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5803 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5804 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5805
a61af66fc99e Initial load
duke
parents:
diff changeset
5806 if (op1->code() == lir_move && op2->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5807 assert(op1->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5808 assert(op2->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5809 LIR_Op1* move1 = (LIR_Op1*)op1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5810 LIR_Op1* move2 = (LIR_Op1*)op2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5811 if (move1->info() == move2->info() && move1->in_opr() == move2->in_opr() && move1->result_opr() == move2->result_opr()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5812 // these moves are exactly equal and can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5813 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5814 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5815
a61af66fc99e Initial load
duke
parents:
diff changeset
5816 } else if (op1->code() == lir_fxch && op2->code() == lir_fxch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5817 assert(op1->as_Op1() != NULL, "fxch must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5818 assert(op2->as_Op1() != NULL, "fxch must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5819 LIR_Op1* fxch1 = (LIR_Op1*)op1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5820 LIR_Op1* fxch2 = (LIR_Op1*)op2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5821 if (fxch1->in_opr()->as_jint() == fxch2->in_opr()->as_jint()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5822 // equal FPU stack operations can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5823 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5824 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5825
a61af66fc99e Initial load
duke
parents:
diff changeset
5826 } else if (op1->code() == lir_fpop_raw && op2->code() == lir_fpop_raw) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5827 // equal FPU stack operations can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5828 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5829 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5830
a61af66fc99e Initial load
duke
parents:
diff changeset
5831 // no optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5832 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5833 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5834
a61af66fc99e Initial load
duke
parents:
diff changeset
5835 void EdgeMoveOptimizer::optimize_moves_at_block_end(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5836 TRACE_LINEAR_SCAN(4, tty->print_cr("optimizing moves at end of block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5837
a61af66fc99e Initial load
duke
parents:
diff changeset
5838 if (block->is_predecessor(block)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5839 // currently we can't handle this correctly.
a61af66fc99e Initial load
duke
parents:
diff changeset
5840 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5841 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5842
a61af66fc99e Initial load
duke
parents:
diff changeset
5843 init_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
5844 int num_preds = block->number_of_preds();
a61af66fc99e Initial load
duke
parents:
diff changeset
5845 assert(num_preds > 1, "do not call otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5846 assert(!block->is_set(BlockBegin::exception_entry_flag), "exception handlers not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
5847
a61af66fc99e Initial load
duke
parents:
diff changeset
5848 // setup a list with the lir-instructions of all predecessors
a61af66fc99e Initial load
duke
parents:
diff changeset
5849 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5850 for (i = 0; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5851 BlockBegin* pred = block->pred_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5852 LIR_OpList* pred_instructions = pred->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5853
a61af66fc99e Initial load
duke
parents:
diff changeset
5854 if (pred->number_of_sux() != 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5855 // this can happen with switch-statements where multiple edges are between
a61af66fc99e Initial load
duke
parents:
diff changeset
5856 // the same blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
5857 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5858 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5859
a61af66fc99e Initial load
duke
parents:
diff changeset
5860 assert(pred->number_of_sux() == 1, "can handle only one successor");
a61af66fc99e Initial load
duke
parents:
diff changeset
5861 assert(pred->sux_at(0) == block, "invalid control flow");
a61af66fc99e Initial load
duke
parents:
diff changeset
5862 assert(pred_instructions->last()->code() == lir_branch, "block with successor must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5863 assert(pred_instructions->last()->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5864 assert(pred_instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5865
a61af66fc99e Initial load
duke
parents:
diff changeset
5866 if (pred_instructions->last()->info() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5867 // can not optimize instructions when debug info is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5868 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5869 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5870
a61af66fc99e Initial load
duke
parents:
diff changeset
5871 // ignore the unconditional branch at the end of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
5872 append_instructions(pred_instructions, pred_instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5873 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5874
a61af66fc99e Initial load
duke
parents:
diff changeset
5875
a61af66fc99e Initial load
duke
parents:
diff changeset
5876 // process lir-instructions while all predecessors end with the same instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
5877 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5878 LIR_Op* op = instruction_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
5879 for (i = 1; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5880 if (operations_different(op, instruction_at(i))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5881 // these instructions are different and cannot be optimized ->
a61af66fc99e Initial load
duke
parents:
diff changeset
5882 // no further optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5883 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5884 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5885 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5886
a61af66fc99e Initial load
duke
parents:
diff changeset
5887 TRACE_LINEAR_SCAN(4, tty->print("found instruction that is equal in all %d predecessors: ", num_preds); op->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5888
a61af66fc99e Initial load
duke
parents:
diff changeset
5889 // insert the instruction at the beginning of the current block
a61af66fc99e Initial load
duke
parents:
diff changeset
5890 block->lir()->insert_before(1, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
5891
a61af66fc99e Initial load
duke
parents:
diff changeset
5892 // delete the instruction at the end of all predecessors
a61af66fc99e Initial load
duke
parents:
diff changeset
5893 for (i = 0; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5894 remove_cur_instruction(i, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5895 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5896 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5897 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5898
a61af66fc99e Initial load
duke
parents:
diff changeset
5899
a61af66fc99e Initial load
duke
parents:
diff changeset
5900 void EdgeMoveOptimizer::optimize_moves_at_block_begin(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5901 TRACE_LINEAR_SCAN(4, tty->print_cr("optimization moves at begin of block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
5902
a61af66fc99e Initial load
duke
parents:
diff changeset
5903 init_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
5904 int num_sux = block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
5905
a61af66fc99e Initial load
duke
parents:
diff changeset
5906 LIR_OpList* cur_instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5907
a61af66fc99e Initial load
duke
parents:
diff changeset
5908 assert(num_sux == 2, "method should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5909 assert(cur_instructions->last()->code() == lir_branch, "block with successor must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5910 assert(cur_instructions->last()->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5911 assert(cur_instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5912
a61af66fc99e Initial load
duke
parents:
diff changeset
5913 if (cur_instructions->last()->info() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5914 // can no optimize instructions when debug info is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5915 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5916 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5917
a61af66fc99e Initial load
duke
parents:
diff changeset
5918 LIR_Op* branch = cur_instructions->at(cur_instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5919 if (branch->info() != NULL || (branch->code() != lir_branch && branch->code() != lir_cond_float_branch)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5920 // not a valid case for optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
5921 // currently, only blocks that end with two branches (conditional branch followed
a61af66fc99e Initial load
duke
parents:
diff changeset
5922 // by unconditional branch) are optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5923 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5924 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5925
a61af66fc99e Initial load
duke
parents:
diff changeset
5926 // now it is guaranteed that the block ends with two branch instructions.
a61af66fc99e Initial load
duke
parents:
diff changeset
5927 // the instructions are inserted at the end of the block before these two branches
a61af66fc99e Initial load
duke
parents:
diff changeset
5928 int insert_idx = cur_instructions->length() - 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5929
a61af66fc99e Initial load
duke
parents:
diff changeset
5930 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5931 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
5932 for (i = insert_idx - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5933 LIR_Op* op = cur_instructions->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5934 if ((op->code() == lir_branch || op->code() == lir_cond_float_branch) && ((LIR_OpBranch*)op)->block() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5935 assert(false, "block with two successors can have only two branch instructions");
a61af66fc99e Initial load
duke
parents:
diff changeset
5936 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5937 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5938 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5939
a61af66fc99e Initial load
duke
parents:
diff changeset
5940 // setup a list with the lir-instructions of all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
5941 for (i = 0; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5942 BlockBegin* sux = block->sux_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5943 LIR_OpList* sux_instructions = sux->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5944
a61af66fc99e Initial load
duke
parents:
diff changeset
5945 assert(sux_instructions->at(0)->code() == lir_label, "block must start with label");
a61af66fc99e Initial load
duke
parents:
diff changeset
5946
a61af66fc99e Initial load
duke
parents:
diff changeset
5947 if (sux->number_of_preds() != 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5948 // this can happen with switch-statements where multiple edges are between
a61af66fc99e Initial load
duke
parents:
diff changeset
5949 // the same blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
5950 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5951 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5952 assert(sux->pred_at(0) == block, "invalid control flow");
a61af66fc99e Initial load
duke
parents:
diff changeset
5953 assert(!sux->is_set(BlockBegin::exception_entry_flag), "exception handlers not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
5954
a61af66fc99e Initial load
duke
parents:
diff changeset
5955 // ignore the label at the beginning of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
5956 append_instructions(sux_instructions, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5957 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5958
a61af66fc99e Initial load
duke
parents:
diff changeset
5959 // process lir-instructions while all successors begin with the same instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
5960 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5961 LIR_Op* op = instruction_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
5962 for (i = 1; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5963 if (operations_different(op, instruction_at(i))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5964 // these instructions are different and cannot be optimized ->
a61af66fc99e Initial load
duke
parents:
diff changeset
5965 // no further optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5966 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5967 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5968 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5969
a61af66fc99e Initial load
duke
parents:
diff changeset
5970 TRACE_LINEAR_SCAN(4, tty->print("----- found instruction that is equal in all %d successors: ", num_sux); op->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5971
a61af66fc99e Initial load
duke
parents:
diff changeset
5972 // insert instruction at end of current block
a61af66fc99e Initial load
duke
parents:
diff changeset
5973 block->lir()->insert_before(insert_idx, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
5974 insert_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
5975
a61af66fc99e Initial load
duke
parents:
diff changeset
5976 // delete the instructions at the beginning of all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
5977 for (i = 0; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5978 remove_cur_instruction(i, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5979 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5980 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5981 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5982
a61af66fc99e Initial load
duke
parents:
diff changeset
5983
a61af66fc99e Initial load
duke
parents:
diff changeset
5984 // Implementation of ControlFlowOptimizer
a61af66fc99e Initial load
duke
parents:
diff changeset
5985
a61af66fc99e Initial load
duke
parents:
diff changeset
5986 ControlFlowOptimizer::ControlFlowOptimizer() :
a61af66fc99e Initial load
duke
parents:
diff changeset
5987 _original_preds(4)
a61af66fc99e Initial load
duke
parents:
diff changeset
5988 {
a61af66fc99e Initial load
duke
parents:
diff changeset
5989 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5990
a61af66fc99e Initial load
duke
parents:
diff changeset
5991 void ControlFlowOptimizer::optimize(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5992 ControlFlowOptimizer optimizer = ControlFlowOptimizer();
a61af66fc99e Initial load
duke
parents:
diff changeset
5993
a61af66fc99e Initial load
duke
parents:
diff changeset
5994 // push the OSR entry block to the end so that we're not jumping over it.
a61af66fc99e Initial load
duke
parents:
diff changeset
5995 BlockBegin* osr_entry = code->at(0)->end()->as_Base()->osr_entry();
a61af66fc99e Initial load
duke
parents:
diff changeset
5996 if (osr_entry) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5997 int index = osr_entry->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
5998 assert(code->at(index) == osr_entry, "wrong index");
a61af66fc99e Initial load
duke
parents:
diff changeset
5999 code->remove_at(index);
a61af66fc99e Initial load
duke
parents:
diff changeset
6000 code->append(osr_entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
6001 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6002
a61af66fc99e Initial load
duke
parents:
diff changeset
6003 optimizer.reorder_short_loops(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6004 optimizer.delete_empty_blocks(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6005 optimizer.delete_unnecessary_jumps(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6006 optimizer.delete_jumps_to_return(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6007 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6008
a61af66fc99e Initial load
duke
parents:
diff changeset
6009 void ControlFlowOptimizer::reorder_short_loop(BlockList* code, BlockBegin* header_block, int header_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6010 int i = header_idx + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6011 int max_end = MIN2(header_idx + ShortLoopSize, code->length());
a61af66fc99e Initial load
duke
parents:
diff changeset
6012 while (i < max_end && code->at(i)->loop_depth() >= header_block->loop_depth()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6013 i++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6014 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6015
a61af66fc99e Initial load
duke
parents:
diff changeset
6016 if (i == code->length() || code->at(i)->loop_depth() < header_block->loop_depth()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6017 int end_idx = i - 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6018 BlockBegin* end_block = code->at(end_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
6019
a61af66fc99e Initial load
duke
parents:
diff changeset
6020 if (end_block->number_of_sux() == 1 && end_block->sux_at(0) == header_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6021 // short loop from header_idx to end_idx found -> reorder blocks such that
a61af66fc99e Initial load
duke
parents:
diff changeset
6022 // the header_block is the last block instead of the first block of the loop
a61af66fc99e Initial load
duke
parents:
diff changeset
6023 TRACE_LINEAR_SCAN(1, tty->print_cr("Reordering short loop: length %d, header B%d, end B%d",
a61af66fc99e Initial load
duke
parents:
diff changeset
6024 end_idx - header_idx + 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
6025 header_block->block_id(), end_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
6026
a61af66fc99e Initial load
duke
parents:
diff changeset
6027 for (int j = header_idx; j < end_idx; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6028 code->at_put(j, code->at(j + 1));
a61af66fc99e Initial load
duke
parents:
diff changeset
6029 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6030 code->at_put(end_idx, header_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6031
a61af66fc99e Initial load
duke
parents:
diff changeset
6032 // correct the flags so that any loop alignment occurs in the right place.
a61af66fc99e Initial load
duke
parents:
diff changeset
6033 assert(code->at(end_idx)->is_set(BlockBegin::backward_branch_target_flag), "must be backward branch target");
a61af66fc99e Initial load
duke
parents:
diff changeset
6034 code->at(end_idx)->clear(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6035 code->at(header_idx)->set(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6036 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6037 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6038 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6039
a61af66fc99e Initial load
duke
parents:
diff changeset
6040 void ControlFlowOptimizer::reorder_short_loops(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6041 for (int i = code->length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6042 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6043
a61af66fc99e Initial load
duke
parents:
diff changeset
6044 if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6045 reorder_short_loop(code, block, i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6046 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6047 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6048
a61af66fc99e Initial load
duke
parents:
diff changeset
6049 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6050 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6051
a61af66fc99e Initial load
duke
parents:
diff changeset
6052 // only blocks with exactly one successor can be deleted. Such blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
6053 // must always end with an unconditional branch to this successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6054 bool ControlFlowOptimizer::can_delete_block(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6055 if (block->number_of_sux() != 1 || block->number_of_exception_handlers() != 0 || block->is_entry_block()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6056 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6057 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6058
a61af66fc99e Initial load
duke
parents:
diff changeset
6059 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6060
a61af66fc99e Initial load
duke
parents:
diff changeset
6061 assert(instructions->length() >= 2, "block must have label and branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6062 assert(instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6063 assert(instructions->last()->as_OpBranch() != NULL, "last instrcution must always be a branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6064 assert(instructions->last()->as_OpBranch()->cond() == lir_cond_always, "branch must be unconditional");
a61af66fc99e Initial load
duke
parents:
diff changeset
6065 assert(instructions->last()->as_OpBranch()->block() == block->sux_at(0), "branch target must be the successor");
a61af66fc99e Initial load
duke
parents:
diff changeset
6066
a61af66fc99e Initial load
duke
parents:
diff changeset
6067 // block must have exactly one successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6068
a61af66fc99e Initial load
duke
parents:
diff changeset
6069 if (instructions->length() == 2 && instructions->last()->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6070 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
6071 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6072 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6073 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6074
a61af66fc99e Initial load
duke
parents:
diff changeset
6075 // substitute branch targets in all branch-instructions of this blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
6076 void ControlFlowOptimizer::substitute_branch_target(BlockBegin* block, BlockBegin* target_from, BlockBegin* target_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6077 TRACE_LINEAR_SCAN(3, tty->print_cr("Deleting empty block: substituting from B%d to B%d inside B%d", target_from->block_id(), target_to->block_id(), block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
6078
a61af66fc99e Initial load
duke
parents:
diff changeset
6079 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6080
a61af66fc99e Initial load
duke
parents:
diff changeset
6081 assert(instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6082 for (int i = instructions->length() - 1; i >= 1; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6083 LIR_Op* op = instructions->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6084
a61af66fc99e Initial load
duke
parents:
diff changeset
6085 if (op->code() == lir_branch || op->code() == lir_cond_float_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6086 assert(op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6087 LIR_OpBranch* branch = (LIR_OpBranch*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6088
a61af66fc99e Initial load
duke
parents:
diff changeset
6089 if (branch->block() == target_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6090 branch->change_block(target_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
6091 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6092 if (branch->ublock() == target_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6093 branch->change_ublock(target_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
6094 }
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::delete_empty_blocks(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6100 int old_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6101 int new_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6102 int num_blocks = code->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
6103
a61af66fc99e Initial load
duke
parents:
diff changeset
6104 while (old_pos < num_blocks) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6105 BlockBegin* block = code->at(old_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
6106
a61af66fc99e Initial load
duke
parents:
diff changeset
6107 if (can_delete_block(block)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6108 BlockBegin* new_target = block->sux_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
6109
a61af66fc99e Initial load
duke
parents:
diff changeset
6110 // propagate backward branch target flag for correct code alignment
a61af66fc99e Initial load
duke
parents:
diff changeset
6111 if (block->is_set(BlockBegin::backward_branch_target_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6112 new_target->set(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6113 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6114
a61af66fc99e Initial load
duke
parents:
diff changeset
6115 // collect a list with all predecessors that contains each predecessor only once
a61af66fc99e Initial load
duke
parents:
diff changeset
6116 // the predecessors of cur are changed during the substitution, so a copy of the
a61af66fc99e Initial load
duke
parents:
diff changeset
6117 // predecessor list is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
6118 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
6119 _original_preds.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
6120 for (j = block->number_of_preds() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6121 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6122 if (_original_preds.index_of(pred) == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6123 _original_preds.append(pred);
a61af66fc99e Initial load
duke
parents:
diff changeset
6124 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6125 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6126
a61af66fc99e Initial load
duke
parents:
diff changeset
6127 for (j = _original_preds.length() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6128 BlockBegin* pred = _original_preds.at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6129 substitute_branch_target(pred, block, new_target);
a61af66fc99e Initial load
duke
parents:
diff changeset
6130 pred->substitute_sux(block, new_target);
a61af66fc99e Initial load
duke
parents:
diff changeset
6131 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6132 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6133 // adjust position of this block in the block list if blocks before
a61af66fc99e Initial load
duke
parents:
diff changeset
6134 // have been deleted
a61af66fc99e Initial load
duke
parents:
diff changeset
6135 if (new_pos != old_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6136 code->at_put(new_pos, code->at(old_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
6137 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6138 new_pos++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6140 old_pos++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6141 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6142 code->truncate(new_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
6143
a61af66fc99e Initial load
duke
parents:
diff changeset
6144 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6145 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6146
a61af66fc99e Initial load
duke
parents:
diff changeset
6147 void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6148 // skip the last block because there a branch is always necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
6149 for (int i = code->length() - 2; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6150 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6151 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6152
a61af66fc99e Initial load
duke
parents:
diff changeset
6153 LIR_Op* last_op = instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6154 if (last_op->code() == lir_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6155 assert(last_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6156 LIR_OpBranch* last_branch = (LIR_OpBranch*)last_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6157
a61af66fc99e Initial load
duke
parents:
diff changeset
6158 assert(last_branch->block() != NULL, "last branch must always have a block as target");
a61af66fc99e Initial load
duke
parents:
diff changeset
6159 assert(last_branch->label() == last_branch->block()->label(), "must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
6160
a61af66fc99e Initial load
duke
parents:
diff changeset
6161 if (last_branch->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6162 if (last_branch->block() == code->at(i + 1)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6163
a61af66fc99e Initial load
duke
parents:
diff changeset
6164 TRACE_LINEAR_SCAN(3, tty->print_cr("Deleting unconditional branch at end of block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
6165
a61af66fc99e Initial load
duke
parents:
diff changeset
6166 // delete last branch instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6167 instructions->truncate(instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
6168
a61af66fc99e Initial load
duke
parents:
diff changeset
6169 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6170 LIR_Op* prev_op = instructions->at(instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
6171 if (prev_op->code() == lir_branch || prev_op->code() == lir_cond_float_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6172 assert(prev_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6173 LIR_OpBranch* prev_branch = (LIR_OpBranch*)prev_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6174
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6175 LIR_Op2* prev_cmp = NULL;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6176
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6177 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
6178 prev_op = instructions->at(j);
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6179 if(prev_op->code() == lir_cmp) {
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6180 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
6181 prev_cmp = (LIR_Op2*)prev_op;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6182 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
6183 }
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6184 }
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6185 assert(prev_cmp != NULL, "should have found comp instruction for branch");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
6186 if (prev_branch->block() == code->at(i + 1) && prev_branch->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6187
a61af66fc99e Initial load
duke
parents:
diff changeset
6188 TRACE_LINEAR_SCAN(3, tty->print_cr("Negating conditional branch and deleting unconditional branch at end of block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
6189
a61af66fc99e Initial load
duke
parents:
diff changeset
6190 // eliminate a conditional branch to the immediate successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6191 prev_branch->change_block(last_branch->block());
a61af66fc99e Initial load
duke
parents:
diff changeset
6192 prev_branch->negate_cond();
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6193 prev_cmp->set_condition(prev_branch->cond());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
6194 instructions->truncate(instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
6195 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6197 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6198 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6199 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6201
a61af66fc99e Initial load
duke
parents:
diff changeset
6202 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6204
a61af66fc99e Initial load
duke
parents:
diff changeset
6205 void ControlFlowOptimizer::delete_jumps_to_return(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6206 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6207 BitMap return_converted(BlockBegin::number_of_blocks());
a61af66fc99e Initial load
duke
parents:
diff changeset
6208 return_converted.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
6209 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6210
a61af66fc99e Initial load
duke
parents:
diff changeset
6211 for (int i = code->length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6212 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6213 LIR_OpList* cur_instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6214 LIR_Op* cur_last_op = cur_instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6215
a61af66fc99e Initial load
duke
parents:
diff changeset
6216 assert(cur_instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6217 if (cur_instructions->length() == 2 && cur_last_op->code() == lir_return) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6218 // the block contains only a label and a return
a61af66fc99e Initial load
duke
parents:
diff changeset
6219 // if a predecessor ends with an unconditional jump to this block, then the jump
a61af66fc99e Initial load
duke
parents:
diff changeset
6220 // can be replaced with a return instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6221 //
a61af66fc99e Initial load
duke
parents:
diff changeset
6222 // Note: the original block with only a return statement cannot be deleted completely
a61af66fc99e Initial load
duke
parents:
diff changeset
6223 // because the predecessors might have other (conditional) jumps to this block
a61af66fc99e Initial load
duke
parents:
diff changeset
6224 // -> this may lead to unnecesary return instructions in the final code
a61af66fc99e Initial load
duke
parents:
diff changeset
6225
a61af66fc99e Initial load
duke
parents:
diff changeset
6226 assert(cur_last_op->info() == NULL, "return instructions do not have debug information");
a61af66fc99e Initial load
duke
parents:
diff changeset
6227 assert(block->number_of_sux() == 0 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
6228 (return_converted.at(block->block_id()) && block->number_of_sux() == 1),
a61af66fc99e Initial load
duke
parents:
diff changeset
6229 "blocks that end with return must not have successors");
a61af66fc99e Initial load
duke
parents:
diff changeset
6230
a61af66fc99e Initial load
duke
parents:
diff changeset
6231 assert(cur_last_op->as_Op1() != NULL, "return must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
6232 LIR_Opr return_opr = ((LIR_Op1*)cur_last_op)->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6233
a61af66fc99e Initial load
duke
parents:
diff changeset
6234 for (int j = block->number_of_preds() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6235 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6236 LIR_OpList* pred_instructions = pred->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6237 LIR_Op* pred_last_op = pred_instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6238
a61af66fc99e Initial load
duke
parents:
diff changeset
6239 if (pred_last_op->code() == lir_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6240 assert(pred_last_op->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6241 LIR_OpBranch* pred_last_branch = (LIR_OpBranch*)pred_last_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6242
a61af66fc99e Initial load
duke
parents:
diff changeset
6243 if (pred_last_branch->block() == block && pred_last_branch->cond() == lir_cond_always && pred_last_branch->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6244 // replace the jump to a return with a direct return
a61af66fc99e Initial load
duke
parents:
diff changeset
6245 // Note: currently the edge between the blocks is not deleted
a61af66fc99e Initial load
duke
parents:
diff changeset
6246 pred_instructions->at_put(pred_instructions->length() - 1, new LIR_Op1(lir_return, return_opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
6247 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6248 return_converted.set_bit(pred->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
6249 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6252 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6253 }
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 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6259 void ControlFlowOptimizer::verify(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6260 for (int i = 0; i < code->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6261 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6262 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6263
a61af66fc99e Initial load
duke
parents:
diff changeset
6264 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
6265 for (j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6266 LIR_OpBranch* op_branch = instructions->at(j)->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
6267
a61af66fc99e Initial load
duke
parents:
diff changeset
6268 if (op_branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6269 assert(op_branch->block() == NULL || code->index_of(op_branch->block()) != -1, "branch target not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6270 assert(op_branch->ublock() == NULL || code->index_of(op_branch->ublock()) != -1, "branch target not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6271 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6272 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6273
a61af66fc99e Initial load
duke
parents:
diff changeset
6274 for (j = 0; j < block->number_of_sux() - 1; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6275 BlockBegin* sux = block->sux_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6276 assert(code->index_of(sux) != -1, "successor not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6277 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6278
a61af66fc99e Initial load
duke
parents:
diff changeset
6279 for (j = 0; j < block->number_of_preds() - 1; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6280 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6281 assert(code->index_of(pred) != -1, "successor not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6282 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6283 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6284 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6285 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6286
a61af66fc99e Initial load
duke
parents:
diff changeset
6287
a61af66fc99e Initial load
duke
parents:
diff changeset
6288 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
6289
a61af66fc99e Initial load
duke
parents:
diff changeset
6290 // Implementation of LinearStatistic
a61af66fc99e Initial load
duke
parents:
diff changeset
6291
a61af66fc99e Initial load
duke
parents:
diff changeset
6292 const char* LinearScanStatistic::counter_name(int counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6293 switch (counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6294 case counter_method: return "compiled methods";
a61af66fc99e Initial load
duke
parents:
diff changeset
6295 case counter_fpu_method: return "methods using fpu";
a61af66fc99e Initial load
duke
parents:
diff changeset
6296 case counter_loop_method: return "methods with loops";
a61af66fc99e Initial load
duke
parents:
diff changeset
6297 case counter_exception_method:return "methods with xhandler";
a61af66fc99e Initial load
duke
parents:
diff changeset
6298
a61af66fc99e Initial load
duke
parents:
diff changeset
6299 case counter_loop: return "loops";
a61af66fc99e Initial load
duke
parents:
diff changeset
6300 case counter_block: return "blocks";
a61af66fc99e Initial load
duke
parents:
diff changeset
6301 case counter_loop_block: return "blocks inside loop";
a61af66fc99e Initial load
duke
parents:
diff changeset
6302 case counter_exception_block: return "exception handler entries";
a61af66fc99e Initial load
duke
parents:
diff changeset
6303 case counter_interval: return "intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6304 case counter_fixed_interval: return "fixed intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6305 case counter_range: return "ranges";
a61af66fc99e Initial load
duke
parents:
diff changeset
6306 case counter_fixed_range: return "fixed ranges";
a61af66fc99e Initial load
duke
parents:
diff changeset
6307 case counter_use_pos: return "use positions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6308 case counter_fixed_use_pos: return "fixed use positions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6309 case counter_spill_slots: return "spill slots";
a61af66fc99e Initial load
duke
parents:
diff changeset
6310
a61af66fc99e Initial load
duke
parents:
diff changeset
6311 // counter for classes of lir instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
6312 case counter_instruction: return "total instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6313 case counter_label: return "labels";
a61af66fc99e Initial load
duke
parents:
diff changeset
6314 case counter_entry: return "method entries";
a61af66fc99e Initial load
duke
parents:
diff changeset
6315 case counter_return: return "method returns";
a61af66fc99e Initial load
duke
parents:
diff changeset
6316 case counter_call: return "method calls";
a61af66fc99e Initial load
duke
parents:
diff changeset
6317 case counter_move: return "moves";
a61af66fc99e Initial load
duke
parents:
diff changeset
6318 case counter_cmp: return "compare";
a61af66fc99e Initial load
duke
parents:
diff changeset
6319 case counter_cond_branch: return "conditional branches";
a61af66fc99e Initial load
duke
parents:
diff changeset
6320 case counter_uncond_branch: return "unconditional branches";
a61af66fc99e Initial load
duke
parents:
diff changeset
6321 case counter_stub_branch: return "branches to stub";
a61af66fc99e Initial load
duke
parents:
diff changeset
6322 case counter_alu: return "artithmetic + logic";
a61af66fc99e Initial load
duke
parents:
diff changeset
6323 case counter_alloc: return "allocations";
a61af66fc99e Initial load
duke
parents:
diff changeset
6324 case counter_sync: return "synchronisation";
a61af66fc99e Initial load
duke
parents:
diff changeset
6325 case counter_throw: return "throw";
a61af66fc99e Initial load
duke
parents:
diff changeset
6326 case counter_unwind: return "unwind";
a61af66fc99e Initial load
duke
parents:
diff changeset
6327 case counter_typecheck: return "type+null-checks";
a61af66fc99e Initial load
duke
parents:
diff changeset
6328 case counter_fpu_stack: return "fpu-stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6329 case counter_misc_inst: return "other instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6330 case counter_other_inst: return "misc. instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6331
a61af66fc99e Initial load
duke
parents:
diff changeset
6332 // counter for different types of moves
a61af66fc99e Initial load
duke
parents:
diff changeset
6333 case counter_move_total: return "total moves";
a61af66fc99e Initial load
duke
parents:
diff changeset
6334 case counter_move_reg_reg: return "register->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6335 case counter_move_reg_stack: return "register->stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6336 case counter_move_stack_reg: return "stack->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6337 case counter_move_stack_stack:return "stack->stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6338 case counter_move_reg_mem: return "register->memory";
a61af66fc99e Initial load
duke
parents:
diff changeset
6339 case counter_move_mem_reg: return "memory->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6340 case counter_move_const_any: return "constant->any";
a61af66fc99e Initial load
duke
parents:
diff changeset
6341
a61af66fc99e Initial load
duke
parents:
diff changeset
6342 case blank_line_1: return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6343 case blank_line_2: return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6344
a61af66fc99e Initial load
duke
parents:
diff changeset
6345 default: ShouldNotReachHere(); return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6346 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6347 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6348
a61af66fc99e Initial load
duke
parents:
diff changeset
6349 LinearScanStatistic::Counter LinearScanStatistic::base_counter(int counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6350 if (counter_idx == counter_fpu_method || counter_idx == counter_loop_method || counter_idx == counter_exception_method) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6351 return counter_method;
a61af66fc99e Initial load
duke
parents:
diff changeset
6352 } else if (counter_idx == counter_loop_block || counter_idx == counter_exception_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6353 return counter_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
6354 } else if (counter_idx >= counter_instruction && counter_idx <= counter_other_inst) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6355 return counter_instruction;
a61af66fc99e Initial load
duke
parents:
diff changeset
6356 } else if (counter_idx >= counter_move_total && counter_idx <= counter_move_const_any) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6357 return counter_move_total;
a61af66fc99e Initial load
duke
parents:
diff changeset
6358 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6359 return invalid_counter;
a61af66fc99e Initial load
duke
parents:
diff changeset
6360 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6361
a61af66fc99e Initial load
duke
parents:
diff changeset
6362 LinearScanStatistic::LinearScanStatistic() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6363 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6364 _counters_sum[i] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6365 _counters_max[i] = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6366 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6367
a61af66fc99e Initial load
duke
parents:
diff changeset
6368 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6369
a61af66fc99e Initial load
duke
parents:
diff changeset
6370 // add the method-local numbers to the total sum
a61af66fc99e Initial load
duke
parents:
diff changeset
6371 void LinearScanStatistic::sum_up(LinearScanStatistic &method_statistic) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6372 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6373 _counters_sum[i] += method_statistic._counters_sum[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
6374 _counters_max[i] = MAX2(_counters_max[i], method_statistic._counters_sum[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6375 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6376 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6377
a61af66fc99e Initial load
duke
parents:
diff changeset
6378 void LinearScanStatistic::print(const char* title) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6379 if (CountLinearScan || TraceLinearScanLevel > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6380 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6381 tty->print_cr("***** LinearScan statistic - %s *****", title);
a61af66fc99e Initial load
duke
parents:
diff changeset
6382
a61af66fc99e Initial load
duke
parents:
diff changeset
6383 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6384 if (_counters_sum[i] > 0 || _counters_max[i] >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6385 tty->print("%25s: %8d", counter_name(i), _counters_sum[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6386
a61af66fc99e Initial load
duke
parents:
diff changeset
6387 if (base_counter(i) != invalid_counter) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6388 tty->print(" (%5.1f%%) ", _counters_sum[i] * 100.0 / _counters_sum[base_counter(i)]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6389 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6390 tty->print(" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
6391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6392
a61af66fc99e Initial load
duke
parents:
diff changeset
6393 if (_counters_max[i] >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6394 tty->print("%8d", _counters_max[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6395 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6396 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6397 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6398 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6399 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6400 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6401
a61af66fc99e Initial load
duke
parents:
diff changeset
6402 void LinearScanStatistic::collect(LinearScan* allocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6403 inc_counter(counter_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6404 if (allocator->has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6405 inc_counter(counter_fpu_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6406 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6407 if (allocator->num_loops() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6408 inc_counter(counter_loop_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6409 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6410 inc_counter(counter_loop, allocator->num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
6411 inc_counter(counter_spill_slots, allocator->max_spills());
a61af66fc99e Initial load
duke
parents:
diff changeset
6412
a61af66fc99e Initial load
duke
parents:
diff changeset
6413 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
6414 for (i = 0; i < allocator->interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6415 Interval* cur = allocator->interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6416
a61af66fc99e Initial load
duke
parents:
diff changeset
6417 if (cur != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6418 inc_counter(counter_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
6419 inc_counter(counter_use_pos, cur->num_use_positions());
a61af66fc99e Initial load
duke
parents:
diff changeset
6420 if (LinearScan::is_precolored_interval(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6421 inc_counter(counter_fixed_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
6422 inc_counter(counter_fixed_use_pos, cur->num_use_positions());
a61af66fc99e Initial load
duke
parents:
diff changeset
6423 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6424
a61af66fc99e Initial load
duke
parents:
diff changeset
6425 Range* range = cur->first();
a61af66fc99e Initial load
duke
parents:
diff changeset
6426 while (range != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6427 inc_counter(counter_range);
a61af66fc99e Initial load
duke
parents:
diff changeset
6428 if (LinearScan::is_precolored_interval(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6429 inc_counter(counter_fixed_range);
a61af66fc99e Initial load
duke
parents:
diff changeset
6430 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6431 range = range->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
6432 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6433 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6434 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6435
a61af66fc99e Initial load
duke
parents:
diff changeset
6436 bool has_xhandlers = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6437 // Note: only count blocks that are in code-emit order
a61af66fc99e Initial load
duke
parents:
diff changeset
6438 for (i = 0; i < allocator->ir()->code()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6439 BlockBegin* cur = allocator->ir()->code()->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6440
a61af66fc99e Initial load
duke
parents:
diff changeset
6441 inc_counter(counter_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6442 if (cur->loop_depth() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6443 inc_counter(counter_loop_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6444 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6445 if (cur->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6446 inc_counter(counter_exception_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6447 has_xhandlers = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
6448 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6449
a61af66fc99e Initial load
duke
parents:
diff changeset
6450 LIR_OpList* instructions = cur->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6451 for (int j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6452 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6453
a61af66fc99e Initial load
duke
parents:
diff changeset
6454 inc_counter(counter_instruction);
a61af66fc99e Initial load
duke
parents:
diff changeset
6455
a61af66fc99e Initial load
duke
parents:
diff changeset
6456 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6457 case lir_label: inc_counter(counter_label); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6458 case lir_std_entry:
a61af66fc99e Initial load
duke
parents:
diff changeset
6459 case lir_osr_entry: inc_counter(counter_entry); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6460 case lir_return: inc_counter(counter_return); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6461
a61af66fc99e Initial load
duke
parents:
diff changeset
6462 case lir_rtcall:
a61af66fc99e Initial load
duke
parents:
diff changeset
6463 case lir_static_call:
a61af66fc99e Initial load
duke
parents:
diff changeset
6464 case lir_optvirtual_call:
a61af66fc99e Initial load
duke
parents:
diff changeset
6465 case lir_virtual_call: inc_counter(counter_call); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6466
a61af66fc99e Initial load
duke
parents:
diff changeset
6467 case lir_move: {
a61af66fc99e Initial load
duke
parents:
diff changeset
6468 inc_counter(counter_move);
a61af66fc99e Initial load
duke
parents:
diff changeset
6469 inc_counter(counter_move_total);
a61af66fc99e Initial load
duke
parents:
diff changeset
6470
a61af66fc99e Initial load
duke
parents:
diff changeset
6471 LIR_Opr in = op->as_Op1()->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6472 LIR_Opr res = op->as_Op1()->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6473 if (in->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6474 if (res->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6475 inc_counter(counter_move_reg_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6476 } else if (res->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6477 inc_counter(counter_move_reg_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
6478 } else if (res->is_address()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6479 inc_counter(counter_move_reg_mem);
a61af66fc99e Initial load
duke
parents:
diff changeset
6480 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6481 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
6482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6483 } else if (in->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6484 if (res->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6485 inc_counter(counter_move_stack_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6486 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6487 inc_counter(counter_move_stack_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
6488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6489 } else if (in->is_address()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6490 assert(res->is_register(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
6491 inc_counter(counter_move_mem_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6492 } else if (in->is_constant()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6493 inc_counter(counter_move_const_any);
a61af66fc99e Initial load
duke
parents:
diff changeset
6494 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6495 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
6496 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6497 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6499
a61af66fc99e Initial load
duke
parents:
diff changeset
6500 case lir_cmp: inc_counter(counter_cmp); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6501
a61af66fc99e Initial load
duke
parents:
diff changeset
6502 case lir_branch:
a61af66fc99e Initial load
duke
parents:
diff changeset
6503 case lir_cond_float_branch: {
a61af66fc99e Initial load
duke
parents:
diff changeset
6504 LIR_OpBranch* branch = op->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
6505 if (branch->block() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6506 inc_counter(counter_stub_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6507 } else if (branch->cond() == lir_cond_always) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6508 inc_counter(counter_uncond_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6509 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6510 inc_counter(counter_cond_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6511 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6512 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6513 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6514
a61af66fc99e Initial load
duke
parents:
diff changeset
6515 case lir_neg:
a61af66fc99e Initial load
duke
parents:
diff changeset
6516 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
6517 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
6518 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
6519 case lir_mul_strictfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6520 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
6521 case lir_div_strictfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6522 case lir_rem:
a61af66fc99e Initial load
duke
parents:
diff changeset
6523 case lir_sqrt:
a61af66fc99e Initial load
duke
parents:
diff changeset
6524 case lir_sin:
a61af66fc99e Initial load
duke
parents:
diff changeset
6525 case lir_cos:
a61af66fc99e Initial load
duke
parents:
diff changeset
6526 case lir_abs:
a61af66fc99e Initial load
duke
parents:
diff changeset
6527 case lir_log10:
a61af66fc99e Initial load
duke
parents:
diff changeset
6528 case lir_log:
a61af66fc99e Initial load
duke
parents:
diff changeset
6529 case lir_logic_and:
a61af66fc99e Initial load
duke
parents:
diff changeset
6530 case lir_logic_or:
a61af66fc99e Initial load
duke
parents:
diff changeset
6531 case lir_logic_xor:
a61af66fc99e Initial load
duke
parents:
diff changeset
6532 case lir_shl:
a61af66fc99e Initial load
duke
parents:
diff changeset
6533 case lir_shr:
a61af66fc99e Initial load
duke
parents:
diff changeset
6534 case lir_ushr: inc_counter(counter_alu); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6535
a61af66fc99e Initial load
duke
parents:
diff changeset
6536 case lir_alloc_object:
a61af66fc99e Initial load
duke
parents:
diff changeset
6537 case lir_alloc_array: inc_counter(counter_alloc); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6538
a61af66fc99e Initial load
duke
parents:
diff changeset
6539 case lir_monaddr:
a61af66fc99e Initial load
duke
parents:
diff changeset
6540 case lir_lock:
a61af66fc99e Initial load
duke
parents:
diff changeset
6541 case lir_unlock: inc_counter(counter_sync); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6542
a61af66fc99e Initial load
duke
parents:
diff changeset
6543 case lir_throw: inc_counter(counter_throw); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6544
a61af66fc99e Initial load
duke
parents:
diff changeset
6545 case lir_unwind: inc_counter(counter_unwind); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6546
a61af66fc99e Initial load
duke
parents:
diff changeset
6547 case lir_null_check:
a61af66fc99e Initial load
duke
parents:
diff changeset
6548 case lir_leal:
a61af66fc99e Initial load
duke
parents:
diff changeset
6549 case lir_instanceof:
a61af66fc99e Initial load
duke
parents:
diff changeset
6550 case lir_checkcast:
a61af66fc99e Initial load
duke
parents:
diff changeset
6551 case lir_store_check: inc_counter(counter_typecheck); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6552
a61af66fc99e Initial load
duke
parents:
diff changeset
6553 case lir_fpop_raw:
a61af66fc99e Initial load
duke
parents:
diff changeset
6554 case lir_fxch:
a61af66fc99e Initial load
duke
parents:
diff changeset
6555 case lir_fld: inc_counter(counter_fpu_stack); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6556
a61af66fc99e Initial load
duke
parents:
diff changeset
6557 case lir_nop:
a61af66fc99e Initial load
duke
parents:
diff changeset
6558 case lir_push:
a61af66fc99e Initial load
duke
parents:
diff changeset
6559 case lir_pop:
a61af66fc99e Initial load
duke
parents:
diff changeset
6560 case lir_convert:
a61af66fc99e Initial load
duke
parents:
diff changeset
6561 case lir_roundfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6562 case lir_cmove: inc_counter(counter_misc_inst); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6563
a61af66fc99e Initial load
duke
parents:
diff changeset
6564 default: inc_counter(counter_other_inst); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6565 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6566 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6567 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6568
a61af66fc99e Initial load
duke
parents:
diff changeset
6569 if (has_xhandlers) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6570 inc_counter(counter_exception_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6571 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6572 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6573
a61af66fc99e Initial load
duke
parents:
diff changeset
6574 void LinearScanStatistic::compute(LinearScan* allocator, LinearScanStatistic &global_statistic) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6575 if (CountLinearScan || TraceLinearScanLevel > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6576
a61af66fc99e Initial load
duke
parents:
diff changeset
6577 LinearScanStatistic local_statistic = LinearScanStatistic();
a61af66fc99e Initial load
duke
parents:
diff changeset
6578
a61af66fc99e Initial load
duke
parents:
diff changeset
6579 local_statistic.collect(allocator);
a61af66fc99e Initial load
duke
parents:
diff changeset
6580 global_statistic.sum_up(local_statistic);
a61af66fc99e Initial load
duke
parents:
diff changeset
6581
a61af66fc99e Initial load
duke
parents:
diff changeset
6582 if (TraceLinearScanLevel > 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6583 local_statistic.print("current local statistic");
a61af66fc99e Initial load
duke
parents:
diff changeset
6584 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6585 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6586 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6587
a61af66fc99e Initial load
duke
parents:
diff changeset
6588
a61af66fc99e Initial load
duke
parents:
diff changeset
6589 // Implementation of LinearTimers
a61af66fc99e Initial load
duke
parents:
diff changeset
6590
a61af66fc99e Initial load
duke
parents:
diff changeset
6591 LinearScanTimers::LinearScanTimers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6592 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6593 timer(i)->reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
6594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6595 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6596
a61af66fc99e Initial load
duke
parents:
diff changeset
6597 const char* LinearScanTimers::timer_name(int idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6598 switch (idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6599 case timer_do_nothing: return "Nothing (Time Check)";
a61af66fc99e Initial load
duke
parents:
diff changeset
6600 case timer_number_instructions: return "Number Instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6601 case timer_compute_local_live_sets: return "Local Live Sets";
a61af66fc99e Initial load
duke
parents:
diff changeset
6602 case timer_compute_global_live_sets: return "Global Live Sets";
a61af66fc99e Initial load
duke
parents:
diff changeset
6603 case timer_build_intervals: return "Build Intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6604 case timer_sort_intervals_before: return "Sort Intervals Before";
a61af66fc99e Initial load
duke
parents:
diff changeset
6605 case timer_allocate_registers: return "Allocate Registers";
a61af66fc99e Initial load
duke
parents:
diff changeset
6606 case timer_resolve_data_flow: return "Resolve Data Flow";
a61af66fc99e Initial load
duke
parents:
diff changeset
6607 case timer_sort_intervals_after: return "Sort Intervals After";
a61af66fc99e Initial load
duke
parents:
diff changeset
6608 case timer_eliminate_spill_moves: return "Spill optimization";
a61af66fc99e Initial load
duke
parents:
diff changeset
6609 case timer_assign_reg_num: return "Assign Reg Num";
a61af66fc99e Initial load
duke
parents:
diff changeset
6610 case timer_allocate_fpu_stack: return "Allocate FPU Stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6611 case timer_optimize_lir: return "Optimize LIR";
a61af66fc99e Initial load
duke
parents:
diff changeset
6612 default: ShouldNotReachHere(); return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6613 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6614 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6615
a61af66fc99e Initial load
duke
parents:
diff changeset
6616 void LinearScanTimers::begin_method() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6617 if (TimeEachLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6618 // reset all timers to measure only current method
a61af66fc99e Initial load
duke
parents:
diff changeset
6619 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6620 timer(i)->reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
6621 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6623 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6624
a61af66fc99e Initial load
duke
parents:
diff changeset
6625 void LinearScanTimers::end_method(LinearScan* allocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6626 if (TimeEachLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6627
a61af66fc99e Initial load
duke
parents:
diff changeset
6628 double c = timer(timer_do_nothing)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6629 double total = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6630 for (int i = 1; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6631 total += timer(i)->seconds() - c;
a61af66fc99e Initial load
duke
parents:
diff changeset
6632 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6633
a61af66fc99e Initial load
duke
parents:
diff changeset
6634 if (total >= 0.0005) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6635 // print all information in one line for automatic processing
a61af66fc99e Initial load
duke
parents:
diff changeset
6636 tty->print("@"); allocator->compilation()->method()->print_name();
a61af66fc99e Initial load
duke
parents:
diff changeset
6637
a61af66fc99e Initial load
duke
parents:
diff changeset
6638 tty->print("@ %d ", allocator->compilation()->method()->code_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
6639 tty->print("@ %d ", allocator->block_at(allocator->block_count() - 1)->last_lir_instruction_id() / 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
6640 tty->print("@ %d ", allocator->block_count());
a61af66fc99e Initial load
duke
parents:
diff changeset
6641 tty->print("@ %d ", allocator->num_virtual_regs());
a61af66fc99e Initial load
duke
parents:
diff changeset
6642 tty->print("@ %d ", allocator->interval_count());
a61af66fc99e Initial load
duke
parents:
diff changeset
6643 tty->print("@ %d ", allocator->_num_calls);
a61af66fc99e Initial load
duke
parents:
diff changeset
6644 tty->print("@ %d ", allocator->num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
6645
a61af66fc99e Initial load
duke
parents:
diff changeset
6646 tty->print("@ %6.6f ", total);
a61af66fc99e Initial load
duke
parents:
diff changeset
6647 for (int i = 1; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6648 tty->print("@ %4.1f ", ((timer(i)->seconds() - c) / total) * 100);
a61af66fc99e Initial load
duke
parents:
diff changeset
6649 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6650 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6651 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6652 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6653 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6654
a61af66fc99e Initial load
duke
parents:
diff changeset
6655 void LinearScanTimers::print(double total_time) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6656 if (TimeLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6657 // correction value: sum of dummy-timer that only measures the time that
a61af66fc99e Initial load
duke
parents:
diff changeset
6658 // is necesary to start and stop itself
a61af66fc99e Initial load
duke
parents:
diff changeset
6659 double c = timer(timer_do_nothing)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6660
a61af66fc99e Initial load
duke
parents:
diff changeset
6661 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6662 double t = timer(i)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6663 tty->print_cr(" %25s: %6.3f s (%4.1f%%) corrected: %6.3f s (%4.1f%%)", timer_name(i), t, (t / total_time) * 100.0, t - c, (t - c) / (total_time - 2 * number_of_timers * c) * 100);
a61af66fc99e Initial load
duke
parents:
diff changeset
6664 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6665 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6666 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6667
a61af66fc99e Initial load
duke
parents:
diff changeset
6668 #endif // #ifndef PRODUCT